tangxu
2024-10-22 6a07c4c846ffbb1e93afdf0260e123e4c145f419
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System;
using System.Collections.Generic;
using DPumpHydr.WinFrmUI.WenSkin.Json.Serialization;
using DPumpHydr.WinFrmUI.WenSkin.Json.Utilities;
 
namespace DPumpHydr.WinFrmUI.WenSkin.Json.Converters
{
    /// <summary>
    /// Converts a <see cref="T:System.Collections.Generic.KeyValuePair`2" /> to and from JSON.
    /// </summary>
    public class KeyValuePairConverter : JsonConverter
    {
        private const string KeyName = "Key";
 
        private const string ValueName = "Value";
 
        private static readonly ThreadSafeStore<Type, ReflectionObject> ReflectionObjectPerType = new ThreadSafeStore<Type, ReflectionObject>(InitializeReflectionObject);
 
        private static ReflectionObject InitializeReflectionObject(Type t)
        {
            Type[] genericArguments = t.GetGenericArguments();
            Type type = ((IList<Type>)genericArguments)[0];
            Type type2 = ((IList<Type>)genericArguments)[1];
            return ReflectionObject.Create(t, t.GetConstructor(new Type[2] { type, type2 }), "Key", "Value");
        }
 
        /// <summary>
        /// Writes the JSON representation of the object.
        /// </summary>
        /// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter" /> to write to.</param>
        /// <param name="value">The value.</param>
        /// <param name="serializer">The calling serializer.</param>
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType());
            DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver;
            writer.WriteStartObject();
            writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Key") : "Key");
            serializer.Serialize(writer, reflectionObject.GetValue(value, "Key"), reflectionObject.GetType("Key"));
            writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Value") : "Value");
            serializer.Serialize(writer, reflectionObject.GetValue(value, "Value"), reflectionObject.GetType("Value"));
            writer.WriteEndObject();
        }
 
        /// <summary>
        /// Reads the JSON representation of the object.
        /// </summary>
        /// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader" /> to read from.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="existingValue">The existing value of object being read.</param>
        /// <param name="serializer">The calling serializer.</param>
        /// <returns>The object value.</returns>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                if (!ReflectionUtils.IsNullableType(objectType))
                {
                    throw JsonSerializationException.Create(reader, "Cannot convert null value to KeyValuePair.");
                }
                return null;
            }
            object obj = null;
            object obj2 = null;
            reader.ReadAndAssert();
            Type key = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType);
            ReflectionObject reflectionObject = ReflectionObjectPerType.Get(key);
            while (reader.TokenType == JsonToken.PropertyName)
            {
                string a = reader.Value.ToString();
                if (string.Equals(a, "Key", StringComparison.OrdinalIgnoreCase))
                {
                    reader.ReadAndAssert();
                    obj = serializer.Deserialize(reader, reflectionObject.GetType("Key"));
                }
                else if (string.Equals(a, "Value", StringComparison.OrdinalIgnoreCase))
                {
                    reader.ReadAndAssert();
                    obj2 = serializer.Deserialize(reader, reflectionObject.GetType("Value"));
                }
                else
                {
                    reader.Skip();
                }
                reader.ReadAndAssert();
            }
            return reflectionObject.Creator(obj, obj2);
        }
 
        /// <summary>
        /// Determines whether this instance can convert the specified object type.
        /// </summary>
        /// <param name="objectType">Type of the object.</param>
        /// <returns>
        ///     <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
        /// </returns>
        public override bool CanConvert(Type objectType)
        {
            Type type = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType);
            if (type.IsValueType() && type.IsGenericType())
            {
                return type.GetGenericTypeDefinition() == typeof(KeyValuePair<, >);
            }
            return false;
        }
    }
}