示例#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);
        }