Beispiel #1
0
        private JsonMaker MakeJsonMaker(Type objectType)
        {
            // Specific custom deserialization
            JsonMaker customMaker = _TranslatorExtensions?.MakeJsonMaker(objectType);

            if (customMaker != null)
            {
                return(customMaker);
            }

            // String
            if (objectType == typeof(string))
            {
                return(obj =>
                {
                    if (obj == null)
                    {
                        return JsonObject.Null;
                    }
                    else
                    {
                        return new JsonObject(obj as string);
                    }
                });
            }

            // Nullable types
            if (objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                JsonMaker subObjectMaker = MakeJsonMaker(objectType.GetGenericArguments()[0]);
                return(obj =>
                {
                    if (obj == null)
                    {
                        return JsonObject.Null;
                    }
                    else
                    {
                        return subObjectMaker(obj);
                    }
                });
            }

            // Enums
            if (objectType.IsEnum)
            {
                return(obj => new JsonObject(obj.ToString()));
            }

            // Simple types
            foreach (var kvp in SIMPLE_TYPES)
            {
                if (objectType == kvp.Key)
                {
                    ConstructorInfo jtc = typeof(JsonObject).GetConstructor(new Type[] { kvp.Key });
                    return(obj => (JsonObject)jtc.Invoke(new object[] { obj }));
                }
            }

            // Parseable from string
            Func <string, object> parser = JsonReflection.GetParser(objectType);

            if (parser != null)
            {
                Func <object, string> toString = JsonReflection.GetToString(objectType);
                return(obj => new JsonObject(toString(obj)));
            }

            // Explicit Dictionary
            JsonReflection.DictionaryInfo dinfo = JsonReflection.IsDictionary(objectType);
            if (dinfo != null)
            {
                if (JsonReflection.GetParser(dinfo.KeyType) == null)
                {
                    throw new InvalidOperationException("Cannot create JsonMaker for type " + objectType.FullName + " because key type " + dinfo.KeyType.FullName + " cannot be parsed from a string");
                }
                JsonMaker    valueMaker    = GetJsonMaker(dinfo.ValueType);
                Type         kvpType       = typeof(KeyValuePair <,>).MakeGenericType(new Type[] { dinfo.KeyType, dinfo.ValueType });
                PropertyInfo keyProperty   = kvpType.GetProperty("Key");
                PropertyInfo valueProperty = kvpType.GetProperty("Value");

                return(obj =>
                {
                    if (obj == null)
                    {
                        return JsonObject.Null;
                    }
                    var result = JsonObject.EmptyDictionary;
                    foreach (var kvp in obj as IEnumerable)
                    {
                        result[keyProperty.GetValue(kvp).ToString()] = valueMaker(valueProperty.GetValue(kvp));
                    }
                    return result;
                });
            }

            // Array
            Type contentType = JsonReflection.GetEnumerableType(objectType);

            if (contentType != null)
            {
                return(obj =>
                {
                    if (obj == null)
                    {
                        return JsonObject.Null;
                    }
                    JsonMaker itemMaker = GetJsonMaker(contentType);
                    var items = new List <JsonObject>();
                    foreach (object item in (IEnumerable)obj)
                    {
                        items.Add(itemMaker(item));
                    }
                    return new JsonObject(items);
                });
            }

            // Object-as-Dictionary (choice of last resort)
            object defaultObj = JsonReflection.GetDefaultMaker(objectType)();

            var getters    = new Dictionary <string, MemberGetter>();
            var types      = new Dictionary <string, Type>();
            var equalities = new Dictionary <string, MethodInfo>();

            FieldInfo[] fields = objectType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (FieldInfo fi in fields)
            {
                if (fi.GetCustomAttribute <JsonIgnoreAttribute>() != null)
                {
                    continue;
                }

                string name = AdjustedFieldName(fi.Name);

                getters[name]    = obj => fi.GetValue(obj);
                types[name]      = fi.FieldType;
                equalities[name] = fi.FieldType.GetMethod("Equals", new Type[] { typeof(object) });
            }

            return(obj =>
            {
                var jfields = new Dictionary <string, JsonObject>();

                foreach (var kvp in getters)
                {
                    object objVal = kvp.Value(obj);
                    object defVal = kvp.Value(defaultObj);
                    MethodInfo equality = equalities[kvp.Key];
                    bool equal = defVal == null ? objVal == null : (bool)equality.Invoke(defVal, new object[] { objVal });
                    if (!equal)
                    {
                        jfields[kvp.Key] = GetJsonMaker(types[kvp.Key])(objVal);
                    }
                }

                return new JsonObject(jfields);
            });
        }