Пример #1
0
        private static object ReadValue(Type inst_type, JsonReader reader, Func <string, object> createFun, Func <string, Type> typeFun, string prefix)
        {
            reader.Read();

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

            //ILRuntime doesn't support nullable valuetype
            Type underlying_type = inst_type;//Nullable.GetUnderlyingType(inst_type);
            Type value_type      = inst_type;

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

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

            if (reader.Token == JsonToken.Single ||
                reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();
                var  vt        = value_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR : value_type;

                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }
                if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum)
                {
                    if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) || json_type == typeof(byte))
                    {
                        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(
                        vt))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][vt];

                    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(
                        vt))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

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

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

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

                //////////////////////////////////// ADD ////////////////////////////////////
                // 类型转换
                if (value_type.Name == "String" && json_type.Name != "String")
                {
                    return(reader.Value.ToString());
                }
                else if (json_type.Name == "String")
                {
                    if (value_type.Name == "Int32")
                    {
                        int re = 0;
                        int.TryParse(reader.Value as string, out re);
                        return(re);
                    }
                    else if (value_type.Name == "Single")
                    {
                        float re = 0;
                        float.TryParse(reader.Value as string, out re);
                        return(re);
                    }
                    else if (value_type.Name == "Double")
                    {
                        double re = 0;
                        double.TryParse(reader.Value as string, out re);
                        return(re);
                    }
                }
                else if (json_type.Name == "Int32")
                {
                    if (value_type.Name == "Double")
                    {
                        return((double)(reader.Value));
                    }
                    else if (value_type.Name == "Single")
                    {
                        return(Convert.ToSingle((int)(reader.Value)));
                    }
                    else if (value_type.Name == "Int64")
                    {
                        return(Convert.ToInt64((int)(reader.Value)));
                    }
                }
                else if (value_type.Name == "Int32" && json_type.Name == "Double")
                {
                    return(Convert.ToInt32((double)(reader.Value)));
                }

                else if (value_type.Name == "Single" && json_type.Name == "Double")
                {
                    return(Convert.ToSingle((double)(reader.Value)));
                }
                else if (value_type.Name == "Int32" && json_type.Name == "Single")
                {
                    return(Convert.ToInt32((float)(reader.Value)));
                }
                else if (value_type.Name == "Double" && json_type.Name == "Single")
                {
                    return(Convert.ToDouble((float)(reader.Value)));
                }
                ////////////////////////////////// ADD OVER /////////////////////////////////
                // No luck
                reader.ShowErrorText();
                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)
                {
                    reader.ShowErrorText();
                    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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader, createFun, typeFun, (prefix == null)?null:(prefix + ".Item"));
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type;
                    item = rt.CheckCLRTypes(item);
                    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)
            {
                //处理自定义类型
                if (typeFun != null)
                {
                    Type realType = typeFun(prefix);
                    if (realType != null)
                    {
                        value_type = realType;
                    }
                }

                AddObjectMetadata(value_type);

                ObjectMetadata t_data = object_metadata[value_type];

                //处理自定义类型
                if (createFun != null)
                {
                    instance = createFun(prefix);
                    if (instance == null)
                    {
                        instance = Activator.CreateInstance(value_type);
                    }
                }
                else if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
                {
                    if (value_type is ILRuntime.Reflection.ILRuntimeWrapperType)
                    {
                        value_type = ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).RealType;
                    }
                    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, createFun, typeFun, (prefix == null) ? null : (prefix + "." + prop_data.Info.Name)));
                        }
                        else
                        {
                            PropertyInfo p_info =
                                (PropertyInfo)prop_data.Info;

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    ReadValue(prop_data.Type, reader, createFun, typeFun, (prefix == null) ? null : (prefix + "." + prop_data.Info.Name)),
                                    null);
                            }
                            else
                            {
                                ReadValue(prop_data.Type, reader, createFun, typeFun, (prefix == null) ? null : (prefix + "." + prop_data.Info.Name));
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                reader.ShowErrorText();
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        var rt = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType : t_data.ElementType;
                        ((IDictionary)instance).Add(
                            property, rt.CheckCLRTypes(ReadValue(
                                                           t_data.ElementType, reader, createFun, typeFun, (prefix == null) ? null : (prefix + ".Item"))));
                    }
                }
            }

            return(instance);
        }
Пример #2
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            Type underlying_type = Nullable.GetUnderlyingType(inst_type);
            Type value_type      = underlying_type ?? inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_type.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.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean ||
                reader.Token == JsonToken.Float)
            {
                Type json_type = reader.Value.GetType();

                //int32 cast to int64 add by Melon
                if (json_type.Name.Equals("Int32") && inst_type.Name.Equals("Int64"))
                {
                    return(reader.Value);
                }
                //int cast to float or double add by Melon
                //if ((json_type.Name.Equals("Double") || json_type.Name.Equals("Float")) && inst_type.Name.Equals("Single"))
                //{
                //    return reader.Value;
                //}

                if (value_type.IsAssignableFrom(json_type))
                {
                    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 (value_type.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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && 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);
                                //use the getSetMethod.invoke instead of SetValue is to suport more platform
                                // such as mono run in ios,jit is forbidden,so the p_info.setValue cannot be used
                                p_info.GetSetMethod().Invoke(instance, new object[] { ReadValue(prop_data.Type, reader) });
                            }

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

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

            return(instance);
        }
Пример #3
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read(inst_type);

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

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (inst_type.IsAssignableFrom(json_type))
                {
                    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(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_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(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

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

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(inst_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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && 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(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];



                reader.Read();


                //如果打开自动识别类型,那么就可以支持已经定义的动态类型
                var  AttrList   = inst_type.GetCustomAttributes(typeof(LitJsonObjectAttribute), false);
                bool NoSelfType = false;
                foreach (var attr in AttrList)
                {
                    var jsonObj = attr as LitJsonObjectAttribute;
                    if (null != jsonObj && jsonObj.NoSelfType == true)
                    {
                        NoSelfType = true;
                    }
                }

                string keyname = (string)reader.Value;
                if (NoSelfType == false && keyname == "selfType")  //第一个字段为selftype 可以多态反射
                {
                    string classname = (string)ReadValue(typeof(string), reader);

                    Type classtype = FindTypeByName(classname);

                    if (null != classtype)
                    {
                        inst_type = classtype;

                        AddObjectMetadata(inst_type);
                        t_data = object_metadata[inst_type];
                    }

                    reader.Read();
                }

                if (inst_type.IsAbstract)
                {
                    while (true)
                    {
                        if (reader.Token == JsonToken.ObjectEnd)
                        {
                            instance = null;
                            break;
                        }

                        ReadSkip(reader);

                        reader.Read();
                    }
                }

                else if (inst_type == typeof(object))//如果期望的类型为object那么会自动转换成JsonData
                {
                    WrapperFactory factory = delegate { return(new JsonData()); };

                    instance = factory();

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

                        string property = (string)reader.Value;

                        ((IDictionary)instance)[property] = ReadValue(factory, reader);

                        reader.Read();
                    }
                }
                else //按类的格式赋值
                {
                    if (reader.Token != JsonToken.ObjectEnd)
                    {
                        instance = Activator.CreateInstance(inst_type);
                    }
                    else
                    {
                        instance = null;
                    }

                    while (true)
                    {
                        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)
                            {
                                if (!reader.SkipNonMembers)
                                {
                                    throw new JsonException(String.Format(
                                                                "The type {0} doesn't have the " +
                                                                "property '{1}'",
                                                                inst_type, property));
                                }
                                else
                                {
                                    ReadSkip(reader);
                                    reader.Read();
                                    continue;
                                }
                            }

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


                        reader.Read();
                    }
                }
            }

            return(instance);
        }
Пример #4
0
        private static void AddArrayMetadata(Type type)
        {
            if (array_metadata.ContainsKey(type))
            {
                return;
            }

            ArrayMetadata data = new ArrayMetadata();

            data.IsArray = type.IsArray;

            if (type.GetInterface("System.Collections.IList") != null)
            {
                data.IsList = true;
            }

            if (type is ILRuntime.Reflection.ILRuntimeWrapperType)
            {
                var wt = (ILRuntime.Reflection.ILRuntimeWrapperType)type;
                if (data.IsArray)
                {
                    data.ElementType = wt.CLRType.ElementType.ReflectionType;
                }
                else
                {
                    data.ElementType = wt.CLRType.GenericArguments[0].Value.ReflectionType;
                }
            }
            else
            {
                foreach (PropertyInfo p_info in type.GetProperties())
                {
                    if (p_info.Name != "Item")
                    {
                        continue;
                    }

                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    if (parameters[0].ParameterType == typeof(int))
                    {
                        data.ElementType = p_info.PropertyType;
                    }
                }
            }

            lock (array_metadata_lock)
            {
                try
                {
                    array_metadata.Add(type, data);
                }
                catch (ArgumentException)
                {
                    return;
                }
            }
        }
Пример #5
0
        static object ReadValue(Type inst_type, JsonData json)
        {
            if (json == null || json.JsonType == JsonType.None || (json.JsonType == JsonType.String && String.IsNullOrEmpty((string)json.Value) && !(inst_type == typeof(string))))
            {
                if (inst_type.IsGenericType && inst_type.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(Activator.CreateInstance(inst_type)); // empty nullable
                }
                if (!inst_type.IsClass && !inst_type.IsArray)
                {
                    throw new JsonException(String.Format("Can't assign null to an instance of type {0}", inst_type));
                }

                return(null);
            }

            object[] attrs;
            if ((attrs = inst_type.GetCustomAttributes(typeof(JsonConverterAttribute), false)) != null && attrs.Length == 1)
            {
                var jca = (JsonConverterAttribute)attrs[0];

                var jc = (IJsonConverter)Activator.CreateInstance(jca.Converter);

                object v_;
                if (jc.Deserialize(json, inst_type, out v_))
                {
                    return(v_);
                }
            }

            if (inst_type.IsGenericType && inst_type.GetGenericTypeDefinition() == typeof(Nullable <>)) // 'json' isn't null -> has a value
            {
                return(Activator.CreateInstance(inst_type, ReadValue(inst_type.GetGenericArguments()[0], json)));
            }

            var v = json.Value;

            switch (json.JsonType)
            {
            case JsonType.Double:
            case JsonType.Int:
            case JsonType.Long:
            case JsonType.String:
            case JsonType.Boolean:
                return(ConvertTo(inst_type, json.Value, json.NetType(inst_type)));

            case JsonType.Array:
            {
                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));
                }

                var inList = (IList <JsonData>)v;

                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();
                }

                for (int i = 0; i < inList.Count; i++)
                {
                    list.Add(ReadValue(elem_type, inList[i]));
                }

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

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)inst).SetValue(list[i], i);
                    }
                }
                else
                {
                    inst = list;
                }

                return(inst);
            }

            case JsonType.Object:
            {
                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                //throw new Exception("type is " + inst_type);
                var inst = Activator.CreateInstance(inst_type);

                var dict = (IDictionary <string, JsonData>)v;

                foreach (var kvp in dict)
                {
                    var prop  = kvp.Key;
                    var value = kvp.Value;

                    PropertyMetadata prop_data;
                    if (TryGetValueIgnCase(t_data.Properties, prop, out prop_data))
                    {
                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(inst, ReadValue(prop_data.Type, value));
                        }
                        else
                        {
                            var p_info = (PropertyInfo)prop_data.Info;

                            var    v_        = ReadValue(prop_data.Type, value);
                            object converted = null;

                            if ((attrs = p_info.GetCustomAttributes(typeof(JsonConverterAttribute), false)) != null && attrs.Length == 1)
                            {
                                var jca = (JsonConverterAttribute)attrs[0];

                                var jc = (IJsonConverter)Activator.CreateInstance(jca.Converter);

                                jc.Deserialize(value, p_info.PropertyType, out converted);
                            }

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(inst, converted ?? ConvertTo(p_info.PropertyType, v_), null);
                            }
                            else
                            {
                                throw new MemberAccessException("Cannot set property '" + p_info + "' to '" + v_ + "'.");
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            throw new JsonException(String.Format("The type {0} doesn't have the property '{1}'", inst_type, prop));
                        }

                        ((IDictionary)inst).Add(prop, ReadValue(t_data.ElementType, value));
                    }
                }

                return(inst);
            }

            default:
                return(null);
            }
        }
Пример #6
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (inst_type.IsAssignableFrom(json_type))
                {
                    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(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_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(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

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

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(inst_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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && 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(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_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)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

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

            return(instance);
        }
Пример #7
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            Type underlying_type = Nullable.GetUnderlyingType(inst_type);
            Type value_type      = underlying_type ?? inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_type.IsClass || underlying_type != null)
                {
                    return(null);
                }
                if (inst_type == typeof(Int32))
                {
                    return(0);
                }
                else if (inst_type == typeof(String))
                {
                    return("");
                }
                return(null);
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (value_type.IsAssignableFrom(json_type))
                {
                    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 (value_type.IsEnum)
                {
                    return(Enum.Parse(value_type, reader.Value.ToString()));
                }

                // 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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item is IJsonReader)
                    {
                        ((IJsonReader)item).OnJsonToObjectFinished();
                    }

                    if (item == null && 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];
                try
                {
                    instance = Activator.CreateInstance(value_type);
                }
                catch (System.Exception e)
                {
                    UnityEngine.Debug.LogError(inst_type.ToString() + " convert failed");
                }


                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];
                        object item = ReadValue(prop_data.Type, reader);
                        if (item is IJsonReader)
                        {
                            ((IJsonReader)item).OnJsonToObjectFinished();
                        }
                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(
                                instance, item);
                        }
                        else
                        {
                            PropertyInfo p_info =
                                (PropertyInfo)prop_data.Info;

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    item,
                                    null);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }
                        Type   keytype = value_type.GenericTypeArguments[0];
                        object value   = ReadValue(
                            value_type.GenericTypeArguments[1], reader);
                        if (value is IJsonReader)
                        {
                            ((IJsonReader)value).OnJsonToObjectFinished();
                        }
                        if (keytype.IsEnum)
                        {
                            ((IDictionary)instance).Add(
                                Enum.Parse(keytype, property), value);
                        }
                        else if (keytype == typeof(int))
                        {
                            ((IDictionary)instance).Add(Convert.ToInt32(property), value);
                        }
                        else
                        {
                            ((IDictionary)instance).Add(
                                property, value);
                        }
                    }
                }
            }

            return(instance);
        }
Пример #8
0
        private static object ReadValue(Type instType, JsonReader reader)
        {
            reader.Read();
            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }
            Type underlyingType = Nullable.GetUnderlyingType(instType);
            Type valueType      = underlyingType ?? instType;

            if (reader.Token == JsonToken.Null)
            {
                        #if JSON_WINRT || (UNITY_METRO && !UNITY_EDITOR)
                /* IsClass is made a getter here as a comparability
                 * patch for WinRT build targets, see Platform.cs */
                if (instType.IsClass() || underlyingType != null)
                {
                        #else
                if (instType.IsClass || underlyingType != null)
                {
                        #endif
                    return(null);
                }
                throw new JsonException(string.Format("Can't assign null to an instance of type {0}", instType));
            }
            if (reader.Token == JsonToken.Real ||
                reader.Token == JsonToken.Natural ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type jsonType = reader.Value.GetType();
                if (valueType.IsAssignableFrom(jsonType))
                {
                    return(reader.Value);
                }
                // Try to find a custom or base importer
                ImporterFunc importer = GetImporter(jsonType, valueType);
                if (importer != null)
                {
                    return(importer(reader.Value));
                }
                // Maybe it's an enum
                        #if JSON_WINRT || (UNITY_METRO && !UNITY_EDITOR)
                /* IsClass is made a getter here as a comparability
                 * patch for WinRT build targets, see Platform.cs */
                if (valueType.IsEnum())
                {
                        #else
                if (valueType.IsEnum)
                {
                        #endif
                    return(Enum.ToObject(valueType, reader.Value));
                }
                // Try using an implicit conversion operator
                MethodInfo convOp = GetConvOp(valueType, jsonType);
                if (convOp != null)
                {
                    return(convOp.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, jsonType, instType));
            }
            object instance = null;
            if (reader.Token == JsonToken.ArrayStart)
            {
                // If there's a custom importer that fits, use it
                ImporterFunc importer = GetImporter(typeof(JsonData), instType);
                if (importer != null)
                {
                    instType = typeof(JsonData);
                }
                AddArrayMetadata(instType);
                ArrayMetadata tdata = arrayMetadata[instType];
                if (!tdata.IsArray && !tdata.IsList)
                {
                    throw new JsonException(string.Format("Type {0} can't act as an array", instType));
                }
                IList list;
                Type  elemType;
                if (!tdata.IsArray)
                {
                    list     = (IList)CreateInstance(instType);
                    elemType = tdata.ElementType;
                }
                else
                {
                    //list = new ArrayList();
                    list     = new List <object>();
                    elemType = instType.GetElementType();
                }
                while (true)
                {
                    object item = ReadValue(elemType, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    list.Add(item);
                }
                if (tdata.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elemType, n);
                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
                if (importer != null)
                {
                    instance = importer(instance);
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                bool   done     = false;
                string property = null;
                reader.Read();
                if (reader.Token == JsonToken.ObjectEnd)
                {
                    done = true;
                }
                else
                {
                    property = (string)reader.Value;
                    if (reader.TypeHinting && property == reader.HintTypeName)
                    {
                        reader.Read();
                        string typeName = (string)reader.Value;
                        reader.Read();
                        if ((string)reader.Value == reader.HintValueName)
                        {
                            valueType = Type.GetType(typeName);
                            object value = ReadValue(valueType, reader);
                            reader.Read();
                            if (reader.Token != JsonToken.ObjectEnd)
                            {
                                throw new JsonException(string.Format("Invalid type hinting object, has too many properties: {0}...", reader.Token));
                            }
                            return(value);
                        }
                        else
                        {
                            throw new JsonException(string.Format("Expected \"{0}\" property for type hinting but instead got \"{1}\"", reader.HintValueName, reader.Value));
                        }
                    }
                }
                // If there's a custom importer that fits, use to create a JsonData type instead.
                // Once the object is deserialzied, it will be invoked to create the actual converted object.
                ImporterFunc importer = GetImporter(typeof(JsonData), valueType);
                if (importer != null)
                {
                    valueType = typeof(JsonData);
                }
                ObjectMetadata tdata = AddObjectMetadata(valueType);
                instance = CreateInstance(valueType);
                bool firstRun = true;
                while (!done)
                {
                    if (firstRun)
                    {
                        firstRun = false;
                    }
                    else
                    {
                        reader.Read();
                        if (reader.Token == JsonToken.ObjectEnd)
                        {
                            break;
                        }
                        property = (string)reader.Value;
                    }
                    PropertyMetadata pdata;
                    if (tdata.Properties.TryGetValue(property, out pdata))
                    {
                        // Don't deserialize a field or property that has a JsonIgnore attribute with deserialization usage.
                        if ((pdata.Ignore & JsonIgnoreWhen.Deserializing) > 0)
                        {
                            ReadSkip(reader);
                            continue;
                        }
                        if (pdata.IsField)
                        {
                            ((FieldInfo)pdata.Info).SetValue(instance, ReadValue(pdata.Type, reader));
                        }
                        else
                        {
                            PropertyInfo pinfo = (PropertyInfo)pdata.Info;
                            if (pinfo.CanWrite)
                            {
                                pinfo.SetValue(instance, ReadValue(pdata.Type, reader), null);
                            }
                            else
                            {
                                ReadValue(pdata.Type, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!tdata.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(string.Format("The type {0} doesn't have the property '{1}'", instType, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }
                        ((IDictionary)instance).Add(property, ReadValue(tdata.ElementType, reader));
                    }
                }
                if (importer != null)
                {
                    instance = importer(instance);
                }
            }
            return(instance);
        }
Пример #9
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();
            if (reader.Token == JsonToken.ArrayEnd)
            {
                return((object)null);
            }
            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(string.Format("Can't assign null to an instance of type {0}", (object)inst_type));
                }
                return((object)null);
            }
            if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || (reader.Token == JsonToken.Long || reader.Token == JsonToken.String) || reader.Token == JsonToken.Boolean)
            {
                Type type = reader.Value.GetType();
                if (inst_type.IsAssignableFrom(type))
                {
                    return(reader.Value);
                }
                if (JsonMapper.custom_importers_table.ContainsKey(type) && JsonMapper.custom_importers_table[type].ContainsKey(inst_type))
                {
                    return(JsonMapper.custom_importers_table[type][inst_type](reader.Value));
                }
                if (JsonMapper.base_importers_table.ContainsKey(type) && JsonMapper.base_importers_table[type].ContainsKey(inst_type))
                {
                    return(JsonMapper.base_importers_table[type][inst_type](reader.Value));
                }
                if (inst_type.IsEnum)
                {
                    return(Enum.ToObject(inst_type, reader.Value));
                }
                MethodInfo convOp = JsonMapper.GetConvOp(inst_type, type);
                if (!(convOp != (MethodInfo)null))
                {
                    throw new JsonException(string.Format("Can't assign value '{0}' (type {1}) to type {2}", reader.Value, (object)type, (object)inst_type));
                }
                return(convOp.Invoke((object)null, new object[1]
                {
                    reader.Value
                }));
            }
            object obj1 = (object)null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                JsonMapper.AddArrayMetadata(inst_type);
                ArrayMetadata arrayMetadata = JsonMapper.array_metadata[inst_type];
                if (!arrayMetadata.IsArray && !arrayMetadata.IsList)
                {
                    throw new JsonException(string.Format("Type {0} can't act as an array", (object)inst_type));
                }
                IList list;
                Type  elementType;
                if (!arrayMetadata.IsArray)
                {
                    list        = (IList)Activator.CreateInstance(inst_type);
                    elementType = arrayMetadata.ElementType;
                }
                else
                {
                    list        = (IList) new ArrayList();
                    elementType = inst_type.GetElementType();
                }
                while (true)
                {
                    object obj2 = JsonMapper.ReadValue(elementType, reader);
                    if (obj2 != null || reader.Token != JsonToken.ArrayEnd)
                    {
                        list.Add(obj2);
                    }
                    else
                    {
                        break;
                    }
                }
                if (arrayMetadata.IsArray)
                {
                    int count = list.Count;
                    obj1 = (object)Array.CreateInstance(elementType, count);
                    for (int index = 0; index < count; ++index)
                    {
                        ((Array)obj1).SetValue(list[index], index);
                    }
                }
                else
                {
                    obj1 = (object)list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                JsonMapper.AddObjectMetadata(inst_type);
                ObjectMetadata objectMetadata = JsonMapper.object_metadata[inst_type];
                obj1 = Activator.CreateInstance(inst_type);
                string key;
                while (true)
                {
                    reader.Read();
                    if (reader.Token != JsonToken.ObjectEnd)
                    {
                        key = (string)reader.Value;
                        if (objectMetadata.Properties.ContainsKey(key))
                        {
                            PropertyMetadata property = objectMetadata.Properties[key];
                            if (property.IsField)
                            {
                                ((FieldInfo)property.Info).SetValue(obj1, JsonMapper.ReadValue(property.Type, reader));
                            }
                            else
                            {
                                PropertyInfo info = (PropertyInfo)property.Info;
                                if (info.CanWrite)
                                {
                                    info.SetValue(obj1, JsonMapper.ReadValue(property.Type, reader), (object[])null);
                                }
                                else
                                {
                                    JsonMapper.ReadValue(property.Type, reader);
                                }
                            }
                        }
                        else if (!objectMetadata.IsDictionary)
                        {
                            if (reader.SkipNonMembers)
                            {
                                JsonMapper.ReadSkip(reader);
                            }
                            else
                            {
                                break;
                            }
                        }
                        else
                        {
                            ((IDictionary)obj1).Add((object)key, JsonMapper.ReadValue(objectMetadata.ElementType, reader));
                        }
                    }
                    else
                    {
                        goto label_45;
                    }
                }
                throw new JsonException(string.Format("The type {0} doesn't have the property '{1}'", (object)inst_type, (object)key));
            }
label_45:
            return(obj1);
        }
Пример #10
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            /*UnityEngine.Debug.Log (inst_type.ToString());
             * UnityEngine.Debug.Log (reader.Token);*/

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                /*Debug.Log (json_type);
                *  Debug.Log (inst_type);*/

                if (inst_type.IsAssignableFrom(json_type))
                {
                    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(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_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(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

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

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(inst_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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item;

                    if (custom_importers_table.ContainsKey(typeof(JsonReader)) &&
                        custom_importers_table[typeof(JsonReader)].ContainsKey(
                            elem_type))
                    {
                        reader.Read();
                        if (reader.Token == JsonToken.ArrayEnd)
                        {
                            break;
                        }

                        ImporterFunc importer =
                            custom_importers_table[typeof(JsonReader)][elem_type];

                        item = importer(reader);
                    }
                    else
                    {
                        item = ReadValue(elem_type, reader);
                    }

                    if (item == null && 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)
            {
                if (custom_importers_table.ContainsKey(typeof(string)) &&
                    custom_importers_table[typeof(string)].ContainsKey(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[typeof(string)][inst_type];

                    return(importer(reader.Value));
                }

                System.Type init_type = inst_type;
                if (inst_type.IsAbstract)
                {
                    Dictionary <string, System.Type> childTypes = ReflectionUtils.GetChildTypes(inst_type);
                    while (reader.Read() && reader.Token != JsonToken.PropertyName)
                    {
                        ;
                    }

                    if (childTypes.ContainsKey(reader.Value.ToString()))
                    {
                        inst_type = childTypes[reader.Value.ToString()];
                    }
                    else
                    {
                        throw new JsonException(String.Format("Attempting to deserialize JSON of type '{0}'. However, the type '{1}' doesn't inherit from the abstract type '{2}'", inst_type, reader.Value, inst_type));
                    }

                    while (reader.Read() && reader.Token != JsonToken.ObjectStart)
                    {
                        ;
                    }
                }

                //Debug.Log ("This is my type: " + inst_type);
                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_type);

                while (true)
                {
                    reader.Read();

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        if (init_type != inst_type)
                        {
                            while (reader.Read() && 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)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        Type[] arguments = ((IDictionary)instance).GetType().GetGenericArguments();
                        Type   keyType   = arguments[0];

                        if (keyType == typeof(System.Int32))
                        {
                            ((IDictionary)instance).Add(
                                int.Parse(property), ReadValue(
                                    arguments[1], reader));
                        }
                        else
                        {
                            ((IDictionary)instance).Add(
                                property, ReadValue(
                                    t_data.ElementType, reader));
                        }
                    }
                }
            }

            return(instance);
        }
Пример #11
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            //ILRuntime doesn't support nullable valuetype
            Type underlying_type = inst_type;//Nullable.GetUnderlyingType(inst_type);
            Type value_type      = inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_type.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.Float ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                var vt = value_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR : value_type;

                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }

                if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum)
                {
                    if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) || json_type == typeof(byte))
                    {
                        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(
                        vt))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][vt];

                    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(
                        vt))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

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

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

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

                if (json_type.ToString() == "System.Int32" && inst_type.ToString() == "System.Boolean")
                {
                    //Debug.Log("int32 to boolean");
                    return((int)reader.Value != 0);
                }

                if (json_type.ToString() == "System.String" && inst_type.ToString() == "System.Int32")
                {
                    //Debug.Log("string to boolean");
                    return(Convert.ToInt32(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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type;
                    item = rt.CheckCLRTypes(item);
                    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];
                if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
                {
                    //这里的value_type = method.GenericArguments[0].ReflectionType; ToObject<T>里的T
                    if (value_type is ILRuntime.Reflection.ILRuntimeWrapperType)
                    {
                        value_type = ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).RealType;
                    }
                    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)
                        {
                            if (((FieldInfo)prop_data.Info).IsStatic)
                            {
                                continue;
                            }
                            ((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)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        var rt = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType : t_data.ElementType;
                        ((IDictionary)instance).Add(
                            property, rt.CheckCLRTypes(ReadValue(
                                                           t_data.ElementType, reader)));
                    }
                }
            }

            return(instance);
        }
Пример #12
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            //ILRuntime doesn't support nullable valuetype
            Type underlying_type = inst_type;//Nullable.GetUnderlyingType(inst_type);
            Type value_type      = inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_type.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.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();
                var  vt        = value_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR : value_type;

                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }
                if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum)
                {
                    if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) || json_type == typeof(byte))
                    {
                        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(
                        vt))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][vt];

                    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(
                        vt))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

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

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(vt, 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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type;
                    if (elem_type is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.IsEnum)
                    {
                        item = (int)item;
                    }
                    else
                    {
                        item = rt.CheckCLRTypes(item);
                    }
                    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];
                if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
                {
                    instance = Activator.CreateInstance(value_type);
                }
                bool isIntKey = t_data.IsDictionary && value_type.GetGenericArguments()[0] == typeof(int);

                var hotArguments = (inst_type as ILRuntimeWrapperType)?.CLRType.GenericArguments?
                                   .Select(i => i.Value)
                                   .ToList()
                                   .FindAll(t => !(t is CLRType));

                var valid = hotArguments?.Count == 1;

                while (true)
                {
                    reader.Read();

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

                    string key = (string)reader.Value;

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

                        if (prop_data.IsField)
                        {
                            var val      = ((FieldInfo)prop_data.Info);
                            var realType = prop_data.Type;
                            if (val.FieldType.ToString() == "ILRuntime.Runtime.Intepreter.ILTypeInstance")
                            {
                                //支持一下本地泛型<热更类型>,这种属于CLRType,会new ILTypeIns导致错误
                                //这里要做的就是把泛型参数里面的热更类型获取出来
                                //但如果有超过1个热更类型在参数里,就没办法判断哪个是这个字段的ILTypeIns了,所以只能1个
                                if (!valid)
                                {
                                    throw new NotSupportedException("仅支持解析1个热更类型做泛型参数的本地泛型类");
                                }

                                realType = hotArguments[0].ReflectionType;
                            }

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

                            var val      = ((PropertyInfo)prop_data.Info);
                            var realType = prop_data.Type;
                            if (val.PropertyType.ToString() == "ILRuntime.Runtime.Intepreter.ILTypeInstance")
                            {
                                if (!valid)
                                {
                                    throw new NotSupportedException("仅支持解析1个热更类型做泛型参数的本地泛型类");
                                }

                                realType = hotArguments[0].ReflectionType;
                            }

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

                        var elem_type = t_data.ElementType;

                        if (inst_type is ILRuntimeWrapperType)//ilrt的字典就获取它第二个泛型参数
                        {
                            elem_type = (inst_type as ILRuntimeWrapperType)?.CLRType.GenericArguments[1].Value.ReflectionType;
                        }
                        else
                        {
                            var dicTypes  = instance.GetType().GetGenericArguments();
                            var converter = System.ComponentModel.TypeDescriptor.GetConverter(dicTypes[0]);
                            if (converter != null)
                            {
                                elem_type = dicTypes[1];
                            }
                        }

                        var    dict      = ((IDictionary)instance);
                        object readValue = ReadValue(elem_type, reader);
                        var    rt        = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType
                            ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType
                            : t_data.ElementType;
                        //value 是枚举的情况没处理,毕竟少
                        if (isIntKey)
                        {
                            var          dictValueType = value_type.GetGenericArguments()[1];
                            IConvertible convertible   = dictValueType as IConvertible;
                            if (convertible == null)
                            {
                                //自定义类型扩展
                                if (dictValueType == typeof(double)) //CheckCLRTypes() 没有double,也可以修改ilruntime源码实现
                                {
                                    var v = Convert.ChangeType(readValue.ToString(), dictValueType);
                                    dict.Add(Convert.ToInt32(key), v);
                                }
                                else
                                {
                                    readValue = rt.CheckCLRTypes(readValue);
                                    dict.Add(Convert.ToInt32(key), readValue);
                                    // throw new JsonException (String.Format("The type {0} doesn't not support",dictValueType));
                                }
                            }
                            else
                            {
                                var v = Convert.ChangeType(readValue, dictValueType);
                                dict.Add(Convert.ToInt32(key), v);
                            }
                        }
                        else
                        {
                            readValue = rt.CheckCLRTypes(readValue);
                            dict.Add(key, readValue);
                        }
                    }
                }
            }

            return(instance);
        }
Пример #13
0
        private static object ReadValue(Type inst_type, JsonReader reader, bool usingTypeInfo = false)
        {
            reader.Read();

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

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (inst_type.IsAssignableFrom(json_type))
                {
                    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(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_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(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

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

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(inst_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;

            #region read array
            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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader, usingTypeInfo);
                    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;
                }
            }
            #endregion
            #region read object
            else if (reader.Token == JsonToken.ObjectStart)
            {
                // if we are using type info we expect the type name as first field in the json
                bool peekedForType = false;
                if (usingTypeInfo && !IsDictionary(inst_type))
                {
                    reader.Read();

                    if ((string)reader.Value == keyTypeInfo)
                    {
                        string t = (string)ReadValue(typeof(System.String), reader);
                        inst_type = Type.GetType(t);
                    }
                    else
                    {
                        // remember that we already read the next member's name
                        peekedForType = true;
                    }
                }

                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_type);

                while (true)
                {
                    // we already read ahead if we didn't find type info
                    if (!peekedForType)
                    {
                        reader.Read();
                    }
                    else
                    {
                        peekedForType = false;
                    }

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

                    string property = (string)reader.Value;

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

                        // Don't deserialize a field or property that has a JsonIgnore attribute with deserialization usage.
                        if ((prop_data.Ignore & JsonIgnoreWhen.Deserializing) > 0)
                        {
                            reader.Read();
                            continue;
                        }

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

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    ReadValue(prop_data.Type, reader, usingTypeInfo),
                                    null);
                            }
                            else
                            {
                                ReadValue(prop_data.Type, reader, usingTypeInfo);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            reader.Read();
                            if (reader.Token == JsonToken.ObjectStart)
                            {
                                while (reader.Token != JsonToken.ObjectEnd)
                                {
                                    reader.Read();
                                }
                            }
                            continue;
                        }
                        // TODO throw exception and return result as part of the exception
//                            throw new JsonException (String.Format (
//                                    "The type {0} doesn't have the " +
//                                    "property '{1}'", inst_type, property));
                        else
                        {
                            ((IDictionary)instance).Add(
                                property, ReadValue(
                                    t_data.ElementType, reader, usingTypeInfo));
                        }
                    }
                }
            }
            #endregion

            return(instance);
        }
Пример #14
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            //ILRuntime doesn't support nullable valuetype
            Type underlying_type = inst_type;//Nullable.GetUnderlyingType(inst_type);
            Type value_type      = inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_type.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.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();
                var  vt        = value_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR : value_type;

                if (vt.FullName.Contains("BindableProperty"))
                {
                    //获取泛型的T
                    string TName       = vt.FullName.Replace("JEngine.Core.BindableProperty`1<", "").Replace(">", "");
                    Type   GenericType = Type.GetType(TName);
                    //强转值到T
                    object[] parameters = new object[1];
                    //泛型赋值的参数
                    parameters[0] = Convert.ChangeType(reader.Value, GenericType);
                    //生成实例且赋值
                    object _instance = Init.appdomain.Instantiate(vt.FullName, parameters);
                    //返回可绑定数据
                    return(_instance);
                }

                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }
                if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum)
                {
                    if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) || json_type == typeof(byte))
                    {
                        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(
                        vt))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][vt];

                    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(
                        vt))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

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

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(vt, 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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type;
                    if (elem_type is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.IsEnum)
                    {
                        item = (int)item;
                    }
                    else
                    {
                        item = rt.CheckCLRTypes(item);
                    }
                    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];
                if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
                {
                    instance = Activator.CreateInstance(value_type);
                }
                bool isIntKey = t_data.IsDictionary && value_type.GetGenericArguments()[0] == typeof(int);
                while (true)
                {
                    reader.Read();

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

                    string key = (string)reader.Value;

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

                        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)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, key));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        var    dict      = ((IDictionary)instance);
                        var    elem_type = t_data.ElementType;
                        object readValue = ReadValue(elem_type, reader);
                        var    rt        = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType
                            ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType
                            : t_data.ElementType;
                        //value 是枚举的情况没处理,毕竟少
                        if (isIntKey)
                        {
                            var          dictValueType = value_type.GetGenericArguments()[1];
                            IConvertible convertible   = dictValueType as IConvertible;
                            if (convertible == null)
                            {
                                //自定义类型扩展
                                if (dictValueType == typeof(double)) //CheckCLRTypes() 没有double,也可以修改ilruntime源码实现
                                {
                                    var v = Convert.ChangeType(readValue.ToString(), dictValueType);
                                    dict.Add(Convert.ToInt32(key), v);
                                }
                                else
                                {
                                    readValue = rt.CheckCLRTypes(readValue);
                                    dict.Add(Convert.ToInt32(key), readValue);
                                    // throw new JsonException (String.Format("The type {0} doesn't not support",dictValueType));
                                }
                            }
                            else
                            {
                                var v = Convert.ChangeType(readValue, dictValueType);
                                dict.Add(Convert.ToInt32(key), v);
                            }
                        }
                        else
                        {
                            readValue = rt.CheckCLRTypes(readValue);
                            dict.Add(key, readValue);
                        }
                    }
                }
            }

            return(instance);
        }
Пример #15
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();
            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }
            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException($"Can't assign null to an instance of type {inst_type}");
                }
                return(null);
            }
            if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || reader.Token == JsonToken.Long || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean)
            {
                Type type = reader.Value.GetType();
                if (inst_type.IsAssignableFrom(type))
                {
                    return(reader.Value);
                }
                if (custom_importers_table.ContainsKey(type) && custom_importers_table[type].ContainsKey(inst_type))
                {
                    ImporterFunc importerFunc = custom_importers_table[type][inst_type];
                    return(importerFunc(reader.Value));
                }
                if (base_importers_table.ContainsKey(type) && base_importers_table[type].ContainsKey(inst_type))
                {
                    ImporterFunc importerFunc = base_importers_table[type][inst_type];
                    return(importerFunc(reader.Value));
                }
                if (inst_type.IsEnum)
                {
                    return(Enum.ToObject(inst_type, reader.Value));
                }
                MethodInfo convOp = GetConvOp(inst_type, type);
                if (convOp != null)
                {
                    return(convOp.Invoke(null, new object[1] {
                        reader.Value
                    }));
                }
                throw new JsonException($"Can't assign value '{reader.Value}' (type {type}) to type {inst_type}");
            }
            object obj = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                if (inst_type.Equals(typeof(object)))
                {
                    inst_type = typeof(List <object>);
                }
                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 ArrayList();
                    elementType = inst_type.GetElementType();
                }
                while (true)
                {
                    bool   flag = true;
                    object obj2 = ReadValue(elementType, reader);
                    if (obj2 == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    list.Add(obj2);
                }
                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)
            {
                if (inst_type.Equals(typeof(object)))
                {
                    inst_type = typeof(Dictionary <string, object>);
                }
                AddObjectMetadata(inst_type);
                ObjectMetadata objectMetadata = object_metadata[inst_type];
                obj = Activator.CreateInstance(inst_type);
                while (true)
                {
                    bool flag = 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.Ignore & JsonIgnoreWhen.Deserializing) > JsonIgnoreWhen.Never)
                        {
                            ReadSkip(reader);
                            continue;
                        }
                        if (propertyMetadata.IsField)
                        {
                            ((FieldInfo)propertyMetadata.Info).SetValue(obj, ReadValue(propertyMetadata.Type, reader));
                            continue;
                        }
                        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)
                    {
                        if (!reader.SkipNonMembers)
                        {
                            throw new JsonException($"The type {inst_type} doesn't have the property '{text}'");
                        }
                        ReadSkip(reader);
                    }
                    else
                    {
                        ((IDictionary)obj).Add(text, ReadValue(objectMetadata.ElementType, reader));
                    }
                }
            }
            return(obj);
        }
Пример #16
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            IList  list;
            Type   elementType;
            object obj3;

            reader.Read();
            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }
            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(string.Format("Can't assign null to an instance of type {0}", inst_type));
                }
                return(null);
            }
            if (((reader.Token == JsonToken.Double) || (reader.Token == JsonToken.Int)) || (((reader.Token == JsonToken.Long) || (reader.Token == JsonToken.String)) || (reader.Token == JsonToken.Boolean)))
            {
                Type c = reader.Value.GetType();
                if (inst_type.IsAssignableFrom(c))
                {
                    return(reader.Value);
                }
                if (custom_importers_table.ContainsKey(c) && custom_importers_table[c].ContainsKey(inst_type))
                {
                    ImporterFunc func = custom_importers_table[c][inst_type];
                    return(func(reader.Value));
                }
                if (base_importers_table.ContainsKey(c) && base_importers_table[c].ContainsKey(inst_type))
                {
                    ImporterFunc func2 = base_importers_table[c][inst_type];
                    return(func2(reader.Value));
                }
                if (inst_type.IsEnum)
                {
                    return(Enum.ToObject(inst_type, reader.Value));
                }
                MethodInfo convOp = GetConvOp(inst_type, c);
                if (convOp == null)
                {
                    throw new JsonException(string.Format("Can't assign value '{0}' (type {1}) to type {2}", reader.Value, c, inst_type));
                }
                return(convOp.Invoke(null, new object[] { reader.Value }));
            }
            object obj2 = null;

            if (reader.Token != JsonToken.ArrayStart)
            {
                goto Label_023E;
            }
            AddArrayMetadata(inst_type);
            ArrayMetadata metadata = array_metadata[inst_type];

            if (!metadata.IsArray && !metadata.IsList)
            {
                throw new JsonException(string.Format("Type {0} can't act as an array", inst_type));
            }
            if (!metadata.IsArray)
            {
                list        = (IList)Activator.CreateInstance(inst_type);
                elementType = metadata.ElementType;
            }
            else
            {
                list        = new ArrayList();
                elementType = inst_type.GetElementType();
            }
Label_01CC:
            obj3 = ReadValue(elementType, reader);
            if (reader.Token != JsonToken.ArrayEnd)
            {
                list.Add(obj3);
                goto Label_01CC;
            }
            if (!metadata.IsArray)
            {
                return(list);
            }
            int count = list.Count;

            obj2 = Array.CreateInstance(elementType, count);
            for (int i = 0; i < count; i++)
            {
                ((Array)obj2).SetValue(list[i], i);
            }
            return(obj2);

Label_023E:
            if (reader.Token != JsonToken.ObjectStart)
            {
                return(obj2);
            }
            AddObjectMetadata(inst_type);
            ObjectMetadata metadata2 = object_metadata[inst_type];

            obj2 = Activator.CreateInstance(inst_type);
            while (true)
            {
                reader.Read();
                if (reader.Token == JsonToken.ObjectEnd)
                {
                    return(obj2);
                }
                string key = (string)reader.Value;
                if (metadata2.Properties.ContainsKey(key))
                {
                    PropertyMetadata metadata3 = metadata2.Properties[key];
                    if (metadata3.IsField)
                    {
                        ((FieldInfo)metadata3.Info).SetValue(obj2, ReadValue(metadata3.Type, reader));
                    }
                    else
                    {
                        PropertyInfo info = (PropertyInfo)metadata3.Info;
                        if (info.CanWrite)
                        {
                            info.SetValue(obj2, ReadValue(metadata3.Type, reader), null);
                        }
                        else
                        {
                            ReadValue(metadata3.Type, reader);
                        }
                    }
                }
                else
                {
                    if (!metadata2.IsDictionary)
                    {
                        throw new JsonException(string.Format("The type {0} doesn't have the property '{1}'", inst_type, key));
                    }
                    ((IDictionary)obj2).Add(key, ReadValue(metadata2.ElementType, reader));
                }
            }
        }
Пример #17
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            //Debug.Log(reader.Token + " " + reader.Value);
            if (reader.Token == JsonToken.Single ||
                reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (inst_type.IsAssignableFrom(json_type))
                {
                    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(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_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(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
                if (inst_type.IsEnum)
                {
                    if (json_type.Name == "String")
                    {
                        int re = 0;
                        int.TryParse(reader.Value as string, out re);
                        return(Enum.ToObject(inst_type, re));
                    }
                    else if (json_type.Name == "Boolean")
                    {
                        return(Enum.ToObject(inst_type, ((bool)(reader.Value))?1:0));
                    }

                    return(Enum.ToObject(inst_type, reader.Value));
                }

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

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

                //////////////////////////////////// ADD ////////////////////////////////////
                // ÀàÐÍת»»
                if (inst_type.Name == "String" && json_type.Name != "String")
                {
                    return(reader.Value.ToString());
                }
                else if (json_type.Name == "String")
                {
                    if (inst_type.Name == "Int32")
                    {
                        int re = 0;
                        int.TryParse(reader.Value as string, out re);
                        return(re);
                    }
                    else if (inst_type.Name == "Single")
                    {
                        float re = 0;
                        float.TryParse(reader.Value as string, out re);
                        return(re);
                    }
                    else if (inst_type.Name == "Double")
                    {
                        double re = 0;
                        double.TryParse(reader.Value as string, out re);
                        return(re);
                    }
                    else if (inst_type.Name == "Boolean")
                    {
                        if (reader.Value == "0")
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                }
                else if (inst_type.Name == "Int32" && json_type.Name == "Double")
                {
                    return(Convert.ToInt32((double)(reader.Value)));
                }
                else if (inst_type.Name == "Double" && json_type.Name == "Int32")
                {
                    return((double)(reader.Value));
                }
                else if (inst_type.Name == "Single" && json_type.Name == "Double")
                {
                    return(Convert.ToSingle((double)(reader.Value)));
                }
                else if (inst_type.Name == "Single" && json_type.Name == "Int32")
                {
                    return(Convert.ToSingle((int)(reader.Value)));
                }
                else if (inst_type.Name == "Int32" && json_type.Name == "Single")
                {
                    return(Convert.ToInt32((float)(reader.Value)));
                }
                else if (inst_type.Name == "Double" && json_type.Name == "Single")
                {
                    return(Convert.ToDouble((float)(reader.Value)));
                }
                else if (inst_type.Name == "Boolean")
                {
                    return(Convert.ToBoolean(reader.Value));
                }


                NGUIDebug.Log((inst_type.Name == "Boolean") + "  " + (json_type.Name == "String"));
                ////////////////////////////////// ADD OVER /////////////////////////////////
                // No luck
                throw new JsonException(String.Format(
                                            "Can't assign value '{0}' (type {1}) to type {2}",
                                            reader.Value, json_type.Name, inst_type.Name));
            }

            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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && 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;
                }

                ////Debug.Log("JsonToken.ArrayStart " + instance.ToString());

                //foreach (var info in list)
                //{
                //    Debug.Log("info = " + info);
                //}
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_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)
                            {
                                //object obj = ReadValue(prop_data.Type, reader);
                                //Debug.Log("yyy property = " + instance + " " + property + " " + p_info);
                                p_info.SetValue(
                                    instance,
                                    ReadValue(prop_data.Type, reader), //obj,//
                                    null);
                            }
                            else
                            {
                                ReadValue(prop_data.Type, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

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

            return(instance);
        }
Пример #18
0
        static object ReadValue(Type inst_type, JsonReader reader, bool readBegin = true)
        {
            if (readBegin)
            {
                reader.Read();
            }

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

            if (reader.Token == JsonToken.Null || (reader.Token == JsonToken.String && String.IsNullOrEmpty((string)reader.Value) && !(inst_type == typeof(string))))
            {
                if (!inst_type.IsClass && !inst_type.IsArray)
                {
                    throw new JsonException(String.Format("Can't assign null to an instance of type {0}", inst_type));
                }

                return(null);
            }

            if (inst_type.IsGenericType && inst_type.GetGenericTypeDefinition() == typeof(Nullable <>)) // isn't null -> has a value
            {
                return(Activator.CreateInstance(inst_type, ReadValue(inst_type.GetGenericArguments()[0], reader, false)));
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                return(ConvertTo(inst_type, reader.Value, reader.Value.GetType()));
            }

            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 (item == null && 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(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_type);

                while (true)
                {
                    reader.Read();

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

                    var property = (string)reader.Value;

                    PropertyMetadata prop_data;
                    if (TryGetValueIgnCase(t_data.Properties, property, out prop_data))
                    {
                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(instance, ReadValue(prop_data.Type, reader));
                        }
                        else
                        {
                            var p_info = (PropertyInfo)prop_data.Info;

                            var v = ReadValue(prop_data.Type, reader);

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

                            ReadSkip(reader);
                            continue;
                        }

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

            return(instance);
        }
Пример #19
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            //ILRuntime doesn't support nullable valuetype
            Type underlying_type = inst_type;//Nullable.GetUnderlyingType(inst_type);
            Type value_type      = inst_type;

            if (reader.Token == JsonToken.Null)
            {
#if NETSTANDARD1_5
                if (inst_type.IsClass() || underlying_type != null)
                {
                    return(null);
                }
#else
                if (inst_type.IsClass || underlying_type != null)
                {
                    return(null);
                }
#endif

                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.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();
                var  vt        = value_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR : value_type;

                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }
                if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum)
                {
                    if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) || json_type == typeof(byte))
                    {
                        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(
                        vt))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][vt];

                    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(
                        vt))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
#if NETSTANDARD1_5
                if (vt.IsEnum())
                {
                    return(Enum.ToObject(vt, reader.Value));
                }
#else
                if (value_type.IsEnum)
                {
                    return(Enum.ToObject(vt, reader.Value));
                }
#endif
                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(vt, 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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                list.Clear();

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type;
                    if (elem_type is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.IsEnum)
                    {
                        item = ( int )item;
                    }
                    else
                    {
                        item = rt.CheckCLRTypes(item);
                    }
                    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];

                if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
                {
                    instance = Activator.CreateInstance(value_type);
                }

                while (true)
                {
                    reader.Read();

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

                    object 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)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        var dict = (( IDictionary )instance);
                        var rt   = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType
                            ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType
                            : t_data.ElementType;
                        //让字典Key自适应类型
                        if (t_data.IsDictionary)
                        {
                            var dicTypes  = instance.GetType().GetGenericArguments();
                            var converter = System.ComponentModel.TypeDescriptor.GetConverter(dicTypes[0]);
                            if (converter != null)
                            {
                                property = converter.ConvertFromString(( string )property);
                                //对于有自定义类当值的字典类型,需要通过CLRType才能获取到对应的类名
                                t_data.ElementType = dicTypes[1].FullName == "ILRuntime.Runtime.Intepreter.ILTypeInstance" ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.GenericArguments[1].Value.ReflectionType : dicTypes[1];
                            }
                        }

                        var readValue      = ReadValue(t_data.ElementType, reader);
                        var checkedCLRType = rt.CheckCLRTypes(readValue);
                        dict.Add(property, checkedCLRType);
                    }
                }
            }

            return(instance);
        }
Пример #20
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

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

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            if (reader.Token == JsonToken.Single || // 让LitJson支持 Single(float)[10/12/2017 ZhangDi]
                reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                // typeof(double).IsAssignableFrom (typeof(float)) 结果为 false [10/12/2017 ZhangDi]
                // 我写的让LitJson支持single逻辑,导致有可能把double识别成single,例如当double d = 2。
                // 所以,这里是允许把single赋值给double的
                if (inst_type == typeof(double) && json_type == typeof(float))
                {
                    return(reader.Value);
                }

                if (inst_type.IsAssignableFrom(json_type))
                {
                    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(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_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(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

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

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(inst_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 ArrayList();
                    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(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_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)
                        {
                            ((IDictionary)instance).Add(property, ReadValue(t_data.ElementType, reader));
                        }
                        else
                        {
                            // 如果A比B多一个成员变量,把A的json数据反序列化成B时,会报这个Exception。而我们不需要报错 [10/12/2017 ZhangDi]
                            //throw new JsonException(String.Format(
                            //		"The type {0} doesn't have the " +
                            //		"property '{1}'", inst_type, property));
                            // 但也要把这个变量读出来,否则会出错
                            ReadValue(t_data.ElementType, reader);
                        }
                    }
                }
            }

            return(instance);
        }
Пример #21
0
        private static void AddArrayMetadata (Type type)
        {
        	if (array_metadata.Contains(type))
                return;

            ArrayMetadata data = new ArrayMetadata();
            data.IsArray = type.IsArray;

            if (type.GetInterface ("System.Collections.IList") != null)
                data.IsList = true;

            foreach (PropertyInfo p_info in type.GetProperties()) {
                if (p_info.Name != "Item")
                    continue;

                ParameterInfo[] parameters = p_info.GetIndexParameters();

                if (parameters.Length != 1)
                    continue;

                if (parameters[0].ParameterType == typeof (int))
                    data.ElementType = p_info.PropertyType;
            }

            lock (array_metadata_lock) {
                try {
                    array_metadata.Add(type, data);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
Пример #22
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();
            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }
            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(string.Format("Can't assign null to an instance of type {0}", inst_type));
                }
                return(null);
            }
            else
            {
                if (reader.Token != JsonToken.Double && reader.Token != JsonToken.Int && reader.Token != JsonToken.Long && reader.Token != JsonToken.String && reader.Token != JsonToken.Boolean)
                {
                    object obj = null;
                    if (reader.Token == JsonToken.ArrayStart)
                    {
                        JsonMapper.AddArrayMetadata(inst_type);
                        ArrayMetadata arrayMetadata = JsonMapper.array_metadata[inst_type];
                        if (!arrayMetadata.IsArray && !arrayMetadata.IsList)
                        {
                            throw new JsonException(string.Format("Type {0} can't act as an array", inst_type));
                        }
                        IList list;
                        Type  elementType;
                        if (!arrayMetadata.IsArray)
                        {
                            list        = (IList)Activator.CreateInstance(inst_type);
                            elementType = arrayMetadata.ElementType;
                        }
                        else
                        {
                            list        = new ArrayList();
                            elementType = inst_type.GetElementType();
                        }
                        for (;;)
                        {
                            object value = JsonMapper.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)
                    {
                        JsonMapper.AddObjectMetadata(inst_type);
                        ObjectMetadata objectMetadata = JsonMapper.object_metadata[inst_type];
                        obj = Activator.CreateInstance(inst_type);
                        string text;
                        for (;;)
                        {
                            reader.Read();
                            if (reader.Token == JsonToken.ObjectEnd)
                            {
                                break;
                            }
                            text = (string)reader.Value;
                            if (objectMetadata.Properties.ContainsKey(text))
                            {
                                PropertyMetadata propertyMetadata = objectMetadata.Properties[text];
                                if (propertyMetadata.IsField)
                                {
                                    ((FieldInfo)propertyMetadata.Info).SetValue(obj, JsonMapper.ReadValue(propertyMetadata.Type, reader));
                                }
                                else
                                {
                                    PropertyInfo propertyInfo = (PropertyInfo)propertyMetadata.Info;
                                    if (propertyInfo.CanWrite)
                                    {
                                        propertyInfo.SetValue(obj, JsonMapper.ReadValue(propertyMetadata.Type, reader), null);
                                    }
                                    else
                                    {
                                        JsonMapper.ReadValue(propertyMetadata.Type, reader);
                                    }
                                }
                            }
                            else
                            {
                                if (!objectMetadata.IsDictionary)
                                {
                                    goto Block_27;
                                }
                                ((IDictionary)obj).Add(text, JsonMapper.ReadValue(objectMetadata.ElementType, reader));
                            }
                        }
                        return(obj);

Block_27:
                        throw new JsonException(string.Format("The type {0} doesn't have the property '{1}'", inst_type, text));
                    }
                    return(obj);
                }
                Type type = reader.Value.GetType();
                if (inst_type.IsAssignableFrom(type))
                {
                    return(reader.Value);
                }
                if (JsonMapper.custom_importers_table.ContainsKey(type) && JsonMapper.custom_importers_table[type].ContainsKey(inst_type))
                {
                    ImporterFunc importerFunc = JsonMapper.custom_importers_table[type][inst_type];
                    return(importerFunc(reader.Value));
                }
                if (JsonMapper.base_importers_table.ContainsKey(type) && JsonMapper.base_importers_table[type].ContainsKey(inst_type))
                {
                    ImporterFunc importerFunc2 = JsonMapper.base_importers_table[type][inst_type];
                    return(importerFunc2(reader.Value));
                }
                if (inst_type.IsEnum)
                {
                    return(Enum.ToObject(inst_type, reader.Value));
                }
                MethodInfo convOp = JsonMapper.GetConvOp(inst_type, type);
                if (convOp != null)
                {
                    return(convOp.Invoke(null, new object[]
                    {
                        reader.Value
                    }));
                }
                throw new JsonException(string.Format("Can't assign value '{0}' (type {1}) to type {2}", reader.Value, type, inst_type));
            }
        }
Пример #23
0
        public static T ReadValueEx <T>(JsonReader reader)
        {
            Type inst_type = typeof(T);

            while (reader.Read())
            {
                if (reader.Token == JsonToken.ArrayEnd || reader.Token == JsonToken.Null)
                {
                    return(default(T));
                }
                if (reader.Token == JsonToken.ArrayStart || reader.Token == JsonToken.ObjectStart)
                {
                    break;
                }
            }

            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 ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && 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(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_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)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        ((IDictionary)instance).Add(
                            property, ReadValue(
                                t_data.ElementType, reader));
                    }
                }
            }
            if (instance == null)
            {
                return(default(T));
            }
            return((T)instance);
        }