Exemple #1
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();
            ITypeInfo typeInfo = TypeFactory.GetTypeInfo(inst_type);

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }
            Type underlyingType = Nullable.GetUnderlyingType(inst_type);
            Type type           = underlyingType ?? inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (typeInfo.IsClass || underlyingType != null)
                {
                    return(null);
                }
                throw new JsonException($"Can't assign null to an instance of type {inst_type}");
            }
            if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || reader.Token == JsonToken.UInt || reader.Token == JsonToken.Long || reader.Token == JsonToken.ULong || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean)
            {
                Type      type2     = reader.Value.GetType();
                ITypeInfo typeInfo2 = TypeFactory.GetTypeInfo(type2);
                if (typeInfo.IsAssignableFrom(typeInfo2))
                {
                    return(reader.Value);
                }
                if (custom_importers_table.ContainsKey(type2) && custom_importers_table[type2].ContainsKey(type))
                {
                    return(custom_importers_table[type2][type](reader.Value));
                }
                if (base_importers_table.ContainsKey(type2) && base_importers_table[type2].ContainsKey(type))
                {
                    return(base_importers_table[type2][type](reader.Value));
                }
                if (typeInfo.IsEnum)
                {
                    return(Enum.ToObject(type, reader.Value));
                }
                MethodInfo convOp = GetConvOp(type, type2);
                if (convOp != null)
                {
                    return(convOp.Invoke(null, new object[1]
                    {
                        reader.Value
                    }));
                }
                throw new JsonException($"Can't assign value '{reader.Value}' (type {type2}) to type {inst_type}");
            }
            object obj = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata arrayMetadata = array_metadata[inst_type];
                if (!arrayMetadata.IsArray && !arrayMetadata.IsList)
                {
                    throw new JsonException($"Type {inst_type} can't act as an array");
                }
                IList list;
                Type  elementType;
                if (!arrayMetadata.IsArray)
                {
                    list        = (IList)Activator.CreateInstance(inst_type);
                    elementType = arrayMetadata.ElementType;
                }
                else
                {
                    list        = new List <object>();
                    elementType = inst_type.GetElementType();
                }
                while (true)
                {
                    object value = ReadValue(elementType, reader);
                    if (reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    list.Add(value);
                }
                if (arrayMetadata.IsArray)
                {
                    int count = list.Count;
                    obj = Array.CreateInstance(elementType, count);
                    for (int i = 0; i < count; i++)
                    {
                        ((Array)obj).SetValue(list[i], i);
                    }
                }
                else
                {
                    obj = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(type);
                ObjectMetadata objectMetadata = object_metadata[type];
                obj = Activator.CreateInstance(type);
                while (true)
                {
                    reader.Read();
                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }
                    string text = (string)reader.Value;
                    if (objectMetadata.Properties.ContainsKey(text))
                    {
                        PropertyMetadata propertyMetadata = objectMetadata.Properties[text];
                        if (propertyMetadata.IsField)
                        {
                            ((FieldInfo)propertyMetadata.Info).SetValue(obj, ReadValue(propertyMetadata.Type, reader));
                        }
                        else
                        {
                            PropertyInfo propertyInfo = (PropertyInfo)propertyMetadata.Info;
                            if (propertyInfo.CanWrite)
                            {
                                propertyInfo.SetValue(obj, ReadValue(propertyMetadata.Type, reader), null);
                            }
                            else
                            {
                                ReadValue(propertyMetadata.Type, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!objectMetadata.IsDictionary)
                        {
                            throw new JsonException($"The type {inst_type} doesn't have the property '{text}'");
                        }
                        ((IDictionary)obj).Add(text, ReadValue(objectMetadata.ElementType, reader));
                    }
                }
            }
            return(obj);
        }
Exemple #2
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();
            var inst_typeInfo = TypeFactory.GetTypeInfo(inst_type);

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }

            //support for nullable types
            Type underlying_type = Nullable.GetUnderlyingType(inst_type);
            Type value_type      = underlying_type ?? inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_typeInfo.IsClass || underlying_type != null)
                {
                    return(null);
                }

                throw new JsonException(String.Format(
                                            "Can't assign null to an instance of type {0}",
                                            inst_type));
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.UInt ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.ULong ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type     = reader.Value.GetType();
                var  json_typeInfo = TypeFactory.GetTypeInfo(json_type);
                if (inst_typeInfo.IsAssignableFrom(json_typeInfo))
                {
                    return(reader.Value);
                }

                // If there's a custom importer that fits, use it
                if (custom_importers_table.ContainsKey(json_type) &&
                    custom_importers_table[json_type].ContainsKey(
                        value_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][value_type];

                    return(importer(reader.Value));
                }

                // Maybe there's a base importer that works
                if (base_importers_table.ContainsKey(json_type) &&
                    base_importers_table[json_type].ContainsKey(
                        value_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][value_type];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
                if (inst_typeInfo.IsEnum)
                {
                    return(Enum.ToObject(value_type, reader.Value));
                }

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(value_type, json_type);

                if (conv_op != null)
                {
                    return(conv_op.Invoke(null,
                                          new object[] { reader.Value }));
                }

                // No luck
                throw new JsonException(String.Format(
                                            "Can't assign value '{0}' (type {1}) to type {2}",
                                            reader.Value, json_type, inst_type));
            }

            object instance = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format(
                                                "Type {0} can't act as an array",
                                                inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new List <object> ();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }

                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(value_type);
                ObjectMetadata t_data = object_metadata[value_type];

                instance = Activator.CreateInstance(value_type);

                while (true)
                {
                    reader.Read();

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }

                    string property = (string)reader.Value;

                    if (t_data.Properties.ContainsKey(property))
                    {
                        PropertyMetadata prop_data =
                            t_data.Properties[property];

                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(
                                instance, ReadValue(prop_data.Type, reader));
                        }
                        else
                        {
                            PropertyInfo p_info =
                                (PropertyInfo)prop_data.Info;

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    ReadValue(prop_data.Type, reader),
                                    null);
                            }
                            else
                            {
                                ReadValue(prop_data.Type, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            throw new JsonException(String.Format(
                                                        "The type {0} doesn't have the " +
                                                        "property '{1}'", inst_type, property));
                        }

                        ((IDictionary)instance).Add(
                            property, ReadValue(
                                t_data.ElementType, reader));
                    }
                }
            }

            return(instance);
        }