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