예제 #1
0
        private static void AddTypeProperties (Type type)
        {
        	if (type_properties.Contains(type))
                return;

            IList props = new ArrayList();

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

                PropertyMetadata p_data = new PropertyMetadata ();
                p_data.Info = p_info;
                p_data.IsField = false;
                props.Add(p_data);
            }

            foreach (FieldInfo f_info in type.GetFields()) {
                PropertyMetadata p_data = new PropertyMetadata ();
                p_data.Info = f_info;
                p_data.IsField = true;

                props.Add(p_data);
            }

            lock (type_properties_lock) {
                try {
                    type_properties.Add(type, props);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
예제 #2
0
        private static void WriteValue(object obj, JsonWriter writer, bool privateWriter, int depth)
        {
            if (depth > maxNestingDepth)
            {
                throw new JsonException(string.Format("Max allowed object depth reached while trying to export from type {0}", obj.GetType()));
            }
            if (obj == null)
            {
                writer.Write(null);
                return;
            }
            if (obj is IJsonWrapper)
            {
                if (privateWriter)
                {
                    writer.TextWriter.Write(((IJsonWrapper)obj).ToJson());
                }
                else
                {
                    ((IJsonWrapper)obj).ToJson(writer);
                }
                return;
            }
            if (obj is string)
            {
                writer.Write((string)obj);
                return;
            }
            if (obj is double)
            {
                writer.Write((double)obj);
                return;
            }
            if (obj is long)
            {
                writer.Write((long)obj);
                return;
            }
            if (obj is bool)
            {
                writer.Write((bool)obj);
                return;
            }
            if (obj is Array)
            {
                writer.WriteArrayStart();
                Array arr      = (Array)obj;
                Type  elemType = arr.GetType().GetElementType();
                foreach (object elem in arr)
                {
                    // if the collection contains polymorphic elements, we need to include type information for deserialization
                    if (writer.TypeHinting && elem != null & elem.GetType() != elemType)
                    {
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(elem.GetType().FullName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(elem, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(elem, writer, privateWriter, depth + 1);
                    }
                }
                writer.WriteArrayEnd();
                return;
            }
            if (obj is IList)
            {
                writer.WriteArrayStart();
                IList list = (IList)obj;
                // collection might be non-generic type like Arraylist
                Type elemType = typeof(object);
                if (list.GetType().GetGenericArguments().Length > 0)
                {
                    // collection is a generic type like List<T>
                    elemType = list.GetType().GetGenericArguments()[0];
                }
                foreach (object elem in list)
                {
                    // if the collection contains polymorphic elements, we need to include type information for deserialization
                    if (writer.TypeHinting && elem != null && elem.GetType() != elemType)
                    {
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(elem.GetType().AssemblyQualifiedName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(elem, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(elem, writer, privateWriter, depth + 1);
                    }
                }
                writer.WriteArrayEnd();
                return;
            }
            if (obj is IDictionary)
            {
                writer.WriteObjectStart();
                IDictionary dict = (IDictionary)obj;
                // collection might be non-generic type like Hashtable
                Type elemType = typeof(object);
                if (dict.GetType().GetGenericArguments().Length > 1)
                {
                    // collection is a generic type like Dictionary<T, V>
                    elemType = dict.GetType().GetGenericArguments()[1];
                }
                foreach (DictionaryEntry entry in dict)
                {
                    writer.WritePropertyName((string)entry.Key);
                    // if the collection contains polymorphic elements, we need to include type information for deserialization
                    if (writer.TypeHinting && entry.Value != null && entry.Value.GetType() != elemType)
                    {
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(entry.Value.GetType().AssemblyQualifiedName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(entry.Value, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(entry.Value, writer, privateWriter, depth + 1);
                    }
                }
                writer.WriteObjectEnd();
                return;
            }
            Type objType = obj.GetType();
            // Try a base or custom importer if one exists
            ExporterFunc exporter = GetExporter(objType);

            if (exporter != null)
            {
                exporter(obj, writer);
                return;
            }
            // Last option, let's see if it's an enum
            if (obj is Enum)
            {
                Type enumType = Enum.GetUnderlyingType(objType);
                if (enumType == typeof(long))
                {
                    writer.Write((long)obj);
                }
                else
                {
                    ExporterFunc enumConverter = GetExporter(enumType);
                    if (enumConverter != null)
                    {
                        enumConverter(obj, writer);
                    }
                }
                return;
            }
            // Okay, it looks like the input should be exported as an object
            ObjectMetadata tdata = AddObjectMetadata(objType);

            writer.WriteObjectStart();
            foreach (string property in tdata.Properties.Keys)
            {
                PropertyMetadata pdata = tdata.Properties[property];
                // Don't serialize soft aliases (which get added to ObjectMetadata.Properties twice).
                if (pdata.Alias != null && property != pdata.Info.Name && tdata.Properties.ContainsKey(pdata.Info.Name))
                {
                    continue;
                }
                // Don't serialize a field or property with the JsonIgnore attribute with serialization usage
                if ((pdata.Ignore & JsonIgnoreWhen.Serializing) > 0)
                {
                    continue;
                }
                if (pdata.IsField)
                {
                    FieldInfo info = (FieldInfo)pdata.Info;
                    if (pdata.Alias != null)
                    {
                        writer.WritePropertyName(pdata.Alias);
                    }
                    else
                    {
                        writer.WritePropertyName(info.Name);
                    }
                    object value = info.GetValue(obj);
                    if (writer.TypeHinting && value != null && info.FieldType != value.GetType())
                    {
                        // the object stored in the field might be a different type that what was declared, need type hinting
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(value.GetType().AssemblyQualifiedName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(value, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(value, writer, privateWriter, depth + 1);
                    }
                }
                else
                {
                    PropertyInfo info = (PropertyInfo)pdata.Info;
                    if (info.CanRead)
                    {
                        if (pdata.Alias != null)
                        {
                            writer.WritePropertyName(pdata.Alias);
                        }
                        else
                        {
                            writer.WritePropertyName(info.Name);
                        }
                        object value = info.GetValue(obj, null);
                        if (writer.TypeHinting && value != null && info.PropertyType != value.GetType())
                        {
                            // the object stored in the property might be a different type that what was declared, need type hinting
                            writer.WriteObjectStart();
                            writer.WritePropertyName(writer.HintTypeName);
                            writer.Write(value.GetType().AssemblyQualifiedName);
                            writer.WritePropertyName(writer.HintValueName);
                            WriteValue(value, writer, privateWriter, depth + 1);
                            writer.WriteObjectEnd();
                        }
                        else
                        {
                            WriteValue(value, writer, privateWriter, depth + 1);
                        }
                    }
                }
            }
            writer.WriteObjectEnd();
        }
예제 #3
0
        private static void AddObjectMetadata (Type type)
        {
        	if (object_metadata.Contains(type))
                return;

            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
                data.IsDictionary = true;

            data.Properties = new Hashtable();

            foreach (PropertyInfo p_info in type.GetProperties ()) {
                if (p_info.Name == "Item") {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                        continue;

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

                    continue;
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                data.Properties.Add(p_info.Name, p_data);
            }

            foreach (FieldInfo f_info in type.GetFields()) {
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = f_info;
                p_data.IsField = true;
                p_data.Type = f_info.FieldType;

                data.Properties.Add(f_info.Name, p_data);
            }

            lock (object_metadata_lock) {
                try {
                    object_metadata.Add(type, data);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
예제 #4
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 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();

                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 NETSTANDARD1_5
                if (value_type.IsEnum())
                {
                    return(Enum.ToObject(value_type, reader.Value));
                }
                #else
                if (value_type.IsEnum)
                {
                    return(Enum.ToObject(value_type, reader.Value));
                }
                #endif
                // 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);
                            }
                            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);
        }
예제 #5
0
        private static ObjectMetadata AddObjectMetadata(Type type)
        {
            if (objectMetadata.ContainsKey(type))
            {
                return(objectMetadata[type]);
            }
            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
            {
                data.IsDictionary = true;
            }
            data.Properties = new Dictionary <string, PropertyMetadata>();
            HashSet <string> ignoredMembers = new HashSet <string>();

            object[] memberAttrs = type.GetCustomAttributes(typeof(JsonIgnoreMember), true);
            foreach (JsonIgnoreMember memberAttr in memberAttrs)
            {
                ignoredMembers.UnionWith(memberAttr.Members);
            }
            // Get all kinds of declared properties
            BindingFlags pflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

            foreach (PropertyInfo pinfo in type.GetProperties(pflags))
            {
                if (pinfo.Name == "Item")
                {
                    ParameterInfo[] parameters = pinfo.GetIndexParameters();
                    if (parameters.Length != 1)
                    {
                        continue;
                    }
                    if (parameters[0].ParameterType == typeof(string))
                    {
                        data.ElementType = pinfo.PropertyType;
                    }
                    continue;
                }
                // Include properties automatically that have at least one public accessor
                bool autoInclude =
                    (pinfo.GetGetMethod() != null && pinfo.GetGetMethod().IsPublic) ||
                    (pinfo.GetSetMethod() != null && pinfo.GetSetMethod().IsPublic);
                // If neither accessor is public and we don't have a [JsonInclude] attribute, skip it
                if (!autoInclude && pinfo.GetCustomAttributes(typeof(JsonInclude), true).Count() == 0)
                {
                    continue;
                }
                PropertyMetadata pdata = new PropertyMetadata();
                pdata.Info = pinfo;
                pdata.Type = pinfo.PropertyType;
                object[] ignoreAttrs = pinfo.GetCustomAttributes(typeof(JsonIgnore), true).ToArray();
                if (ignoreAttrs.Length > 0)
                {
                    pdata.Ignore = ((JsonIgnore)ignoreAttrs[0]).Usage;
                }
                else if (ignoredMembers.Contains(pinfo.Name))
                {
                    pdata.Ignore = JsonIgnoreWhen.Serializing | JsonIgnoreWhen.Deserializing;
                }
                object[] aliasAttrs = pinfo.GetCustomAttributes(typeof(JsonAlias), true).ToArray();
                if (aliasAttrs.Length > 0)
                {
                    JsonAlias aliasAttr = (JsonAlias)aliasAttrs[0];
                    if (aliasAttr.Alias == pinfo.Name)
                    {
                        throw new JsonException(string.Format("Alias name '{0}' must be different from the property it represents for type '{1}'", pinfo.Name, type));
                    }
                    if (data.Properties.ContainsKey(aliasAttr.Alias))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the property or alias name '{1}'", type, aliasAttr.Alias));
                    }
                    pdata.Alias = aliasAttr.Alias;
                    if (aliasAttr.AcceptOriginal)
                    {
                        data.Properties.Add(pinfo.Name, pdata);
                    }
                }
                if (pdata.Alias != null)
                {
                    data.Properties.Add(pdata.Alias, pdata);
                }
                else
                {
                    if (data.Properties.ContainsKey(pinfo.Name))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the property or alias name '{1}'", type, pinfo.Name));
                    }
                    data.Properties.Add(pinfo.Name, pdata);
                }
            }
            // Get all kinds of declared fields
            BindingFlags fflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

            foreach (FieldInfo finfo in type.GetFields(fflags))
            {
                // If the field isn't public and doesn't have an [Include] attribute, skip it
                if (!finfo.IsPublic && finfo.GetCustomAttributes(typeof(JsonInclude), true).Count() == 0)
                {
                    continue;
                }
                PropertyMetadata pdata = new PropertyMetadata();
                pdata.Info    = finfo;
                pdata.IsField = true;
                pdata.Type    = finfo.FieldType;
                object[] ignoreAttrs = finfo.GetCustomAttributes(typeof(JsonIgnore), true).ToArray();
                if (ignoreAttrs.Length > 0)
                {
                    pdata.Ignore = ((JsonIgnore)ignoreAttrs[0]).Usage;
                }
                else if (ignoredMembers.Contains(finfo.Name))
                {
                    pdata.Ignore = JsonIgnoreWhen.Serializing | JsonIgnoreWhen.Deserializing;
                }
                object[] aliasAttrs = finfo.GetCustomAttributes(typeof(JsonAlias), true).ToArray();
                if (aliasAttrs.Length > 0)
                {
                    JsonAlias aliasAttr = (JsonAlias)aliasAttrs[0];
                    if (aliasAttr.Alias == finfo.Name)
                    {
                        throw new JsonException(string.Format("Alias name '{0}' must be different from the field it represents for type '{1}'", finfo.Name, type));
                    }
                    if (data.Properties.ContainsKey(aliasAttr.Alias))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the field or alias name '{1}'", type, aliasAttr.Alias));
                    }
                    pdata.Alias = aliasAttr.Alias;
                    if (aliasAttr.AcceptOriginal)
                    {
                        data.Properties.Add(finfo.Name, pdata);
                    }
                }
                if (pdata.Alias != null)
                {
                    data.Properties.Add(pdata.Alias, pdata);
                }
                else
                {
                    if (data.Properties.ContainsKey(finfo.Name))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the field or alias name '{1}'", type, finfo.Name));
                    }
                    data.Properties.Add(finfo.Name, pdata);
                }
            }
            objectMetadata.Add(type, data);
            return(data);
        }
예제 #6
0
        private static void AddObjectMetadata(Type type)
        {
            if (object_metadata.ContainsKey(type))
            {
                return;
            }

            ObjectMetadata data = new ObjectMetadata();

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

            data.Properties = new Dictionary <string, PropertyMetadata>();

            foreach (PropertyInfo p_info in type.GetProperties())
            {
                if (p_info.Name == "Item")
                {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

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

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

                    continue;
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                data.Properties.Add(p_info.Name, p_data);
            }

            foreach (FieldInfo f_info in type.GetFields())
            {
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info    = f_info;
                p_data.IsField = true;
                p_data.Type    = f_info.FieldType;

                data.Properties.Add(f_info.Name, p_data);
            }

            lock (object_metadata_lock)
            {
                try
                {
                    object_metadata.Add(type, data);
                }
                catch (ArgumentException)
                {
                    return;
                }
            }
        }
예제 #7
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);
        }
예제 #8
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);
        }
 private static bool IsPropertyIgnored(PropertyMetadata p_data)
 {
     IgnoreAttribute[] attr = (IgnoreAttribute[])p_data.Info.GetCustomAttributes(typeof(IgnoreAttribute), false);
     return(0 < attr.Length);
 }
예제 #10
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;
#if ILRUNTIME
                if (value_type is ILRuntime.Reflection.ILRuntimeWrapperType)
                {
                    vt = ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR;
                }
#endif
                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }
#if ILRUNTIME
                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);
                    }
                }
#endif
                // 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.Parse(vt, reader.Value.ToString()));
                }

                // 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;
                    }
#if ILRUNTIME
                    var rt = elem_type;
                    if (elem_type is ILRuntime.Reflection.ILRuntimeType)
                    {
                        rt = ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.TypeForCLR;
                    }
                    item = rt.CheckCLRTypes(item);
#endif
                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n  = list.Count;
                    var rt = elem_type;
#if ILRUNTIME
                    if (elem_type is ILRuntime.Reflection.ILRuntimeType)
                    {
                        rt = ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.TypeForCLR;
                    }
#endif
                    instance = Array.CreateInstance(rt, 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 ILRUNTIME
                if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
#endif
                {
#if ILRUNTIME
                    if (value_type is ILRuntime.Reflection.ILRuntimeWrapperType)
                    {
                        value_type = ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).RealType;
                    }
#endif
                    instance = Activator.CreateInstance(value_type);
                }
                while (true)
                {
                    reader.Read();

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

                    object property = 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
                            {
                                //单独适配proto的repeatedProperty
                                if (typeof(IList).IsAssignableFrom(prop_data.Type))
                                {
                                    var sourceList = (IList)p_info.GetValue(instance);
                                    foreach (var o in (IList)ReadValue(prop_data.Type, reader))
                                    {
                                        sourceList.Add(o);
                                    }
                                }
                            }
                        }
                    }
                    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;
                            }
                        }

                        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);
                                t_data.ElementType = dicTypes[1];
                            }
                        }

                        var rt = t_data.ElementType;
#if ILRUNTIME
                        if (t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType)
                        {
                            rt = ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType;
                        }
                        ((IDictionary)instance).Add(property,
                                                    rt.CheckCLRTypes(ReadValue(t_data.ElementType, reader)));
#else
                        ((IDictionary)instance).Add(property, ReadValue(t_data.ElementType, reader));
#endif
                    }
                }
            }

            return(instance);
        }