object DeserializeDictionary(object inInstance, IKey inKey, Type declaredType, int inInheriteDeep, int inStructDeep, ILogPrinter inLogger) { Type[] gen_args = declaredType.GetGenericArguments(); if (gen_args.Length < 2) { LogError(inLogger, string.Format("DeserializeDictionary: Generic Arguments are None. Type {0}", declaredType.Name)); return(inInstance); } object instance = inInstance; // Instantiate if necessary if (instance == null) { instance = _reflectionProvider.Instantiate(declaredType, inLogger); } var dictionary = instance as IDictionary; Type keyDeclaredType = gen_args[0]; Type valueDeclaredType = gen_args[1]; IKey tree_key = inKey.GetChild("BaseDictionary"); if (tree_key == null) { tree_key = inKey; } for (int i = 0; i < tree_key.GetChildCount(); ++i) { IKey sub_key = tree_key.GetChild(i); object dic_key; if (!ReflectionHelper.StringToAtomicValue(sub_key.GetName(), keyDeclaredType, out dic_key, _reflectionProvider, inLogger)) { LogError(inLogger, string.Format("SubKey {0} [{3}] for dictionary with key type {1} can't convert value {2}", tree_key, keyDeclaredType.Name, sub_key.GetName(), tree_key.GetPath())); } else { object dic_value = DeserializeInternal(null, sub_key, valueDeclaredType, 0, inStructDeep + 1, inLogger); if (dictionary.Contains(dic_key)) { dictionary.Remove(dic_key); } dictionary.Add(dic_key, dic_value); } } return(instance); }
//public static bool IsDefault(object value, IReflectionProvider provider) //{ // if (value is string) // return (string)value == string.Empty; // if (value is char) // return (char)value == '\0'; // if(IsINT(value)) // return Convert.ToInt64(value) == 0; // if (IsUINT(value)) // return Convert.ToUInt64(value) == 0; // if (IsFLOAT(value)) // return Convert.ToDecimal(value) == 0; // if (value is bool) // return (bool)value == false; // if (value is ICollection) // return (value as ICollection).Count == 0; // if (value is Array) // return (value as Array).Length == 0; // Type type = value.GetType(); // if (type.IsEnum) // return (int)value == 0; // if (type.IsHashSet()) // return (int)provider.GetValue(type // .GetProperty("Count", BindingFlags.ExactBinding | ReflectionHelper.PublicInstanceMembers, null, typeof(int), Type.EmptyTypes, null), // value) == 0; // return value.Equals(provider.Instantiate(type)); //} public static object GetDefaultValue(Type inType, IReflectionProvider provider, ILogPrinter inLogger) { if (inType.IsValueType) { return(provider.Instantiate(inType, inLogger)); } return(null); }
public static bool IsDefault(object value, IReflectionProvider provider, ILogPrinter inLogger) { Type type = value.GetType(); if (type.IsValueType) { var t = provider.Instantiate(type, inLogger); return(t.Equals(value)); } else { if (value == null) { return(true); } if (value is string) { return(string.IsNullOrEmpty((string)value)); } if (value is ICollection) { return((value as ICollection).Count == 0); } if (type.IsHashSet()) { return((int)provider.GetValue(type .GetProperty("Count", BindingFlags.ExactBinding | ReflectionHelper.PublicInstanceMembers, null, typeof(int), Type.EmptyTypes, null), value) == 0); } return(false); } }
public object DeserializeInternal(SerializedObject serialized, Type declaredType, object existingInstance) { var type = declaredType; var instance = existingInstance; // Atomic or null values if (serialized is SerializedAtom) { // The current value is replaced; they're immutable instance = (serialized as SerializedAtom).Value; } else if (serialized is SerializedXml) { var it = (serialized as SerializedXml); if (IsXmlType(declaredType)) { using (var sr = new StringReader((serialized as SerializedXml).Value)) using (var xr = XmlReader.Create(sr, new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment })) { instance = _reflectionProvider.Instantiate(declaredType); var readXml = instance as IXmlSerializable; if (readXml == null) { throw new Exception("DeserializeInternal error. readXml is null"); } readXml.ReadXml(xr); } } else if (IsSerializable(declaredType)) { using (var ms = new MemoryStream(Encoding.Default.GetBytes(it.Value))) { return(serializer.Deserialize(ms)); } } } // Dictionaries else if (type.IsGenericDictionary()) { // Instantiate if necessary if (instance == null) { instance = _reflectionProvider.Instantiate(type); } var dictionary = instance as IDictionary; if (dictionary == null) { throw new Exception("DeserializeInternal error. dictionary is null"); } var genericArguments = dictionary.GetType().GetGenericArguments(); var keyDeclaredType = genericArguments[0]; var valueDeclaredType = genericArguments[1]; var serializedAggregation = serialized as SerializedAggregate; if (serializedAggregation == null) { throw new Exception("DeserializeInternal error. serializedAggregation is null"); } foreach (var key in serializedAggregation.Children.Keys) { // Dictionaries always contain atoms as keys SafeAddToDictionary(dictionary, DeserializeInternal(key as SerializedObject, keyDeclaredType, null), DeserializeInternal(serializedAggregation.Children[key], valueDeclaredType, null)); } } // Arrays, lists and sets (any collection excluding dictionaries) else if (type.IsGenericCollection()) { var isArray = type.IsArray; var isHashSet = type.IsHashSet(); var serializedCollection = serialized as SerializedCollection; if (serializedCollection == null) { throw new Exception("DeserializeInternal error. serializedCollection is null"); } var declaredItemType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0]; var genericListType = typeof(System.Collections.Generic.List <>).MakeGenericType(declaredItemType); // Instantiate if necessary if (instance == null) { if (isArray) { instance = Array.CreateInstance(declaredItemType, serializedCollection.Items.Count); } else if (type.IsAssignableFrom(genericListType)) { instance = Activator.CreateInstance(genericListType); } else { if (declaredType.HasParameterlessConstructor()) { instance = _reflectionProvider.Instantiate(declaredType) as IEnumerable; } else if (serializedCollection.Type.HasParameterlessConstructor()) { instance = _reflectionProvider.Instantiate(serializedCollection.Type) as IEnumerable; } } } MethodHandler addToHashSet = null; if (isHashSet) { addToHashSet = _reflectionProvider.GetDelegate(type.GetMethod("Add")); } var valueIndex = 0; foreach (var item in serializedCollection.Items) { var value = DeserializeInternal(item, declaredItemType, null); if (isArray) { var list = instance as IList; if (list == null) { throw new Exception("DeserializeInternal collection error. list is null"); } list[valueIndex++] = value; } else if (isHashSet) { // Potential problem if set already contains key... addToHashSet(instance, value); } else if (instance is IList) { (instance as IList).Add(value); } else { throw new NotImplementedException(); } } } // Everything else (serialized with recursive property reflection) else { var mustInstantiate = instance == null; if (serialized.Type != null && declaredType != serialized.Type) { type = serialized.Type; mustInstantiate = true; } if (mustInstantiate) { instance = _reflectionProvider.Instantiate(type); } var serializedAggregation = serialized as SerializedAggregate; if (serializedAggregation == null) { throw new Exception("DeserializeInternal collection error. serializedAggregation is null"); } foreach (var memberInfo in _reflectionProvider.GetSerializableMembers(type)) { var memberAttr = _reflectionProvider.GetSingleAttributeOrDefault <SerializationAttribute>(memberInfo); if (memberAttr.Ignore) { continue; } var memberType = memberInfo.GetMemberType(); var name = memberAttr.Name ?? memberInfo.Name; // Checking if it's a class before doing GetValue doesn't speed up the process var valueFound = serializedAggregation.Children.ContainsKey(name); if (!valueFound) { if (memberAttr.Required) { throw new InvalidOperationException(string.Format("MissingRequiredValue {0} {1}", name, type.Name)); } } else { try { var currentValue = _reflectionProvider.GetValue(memberInfo, instance); var readValue = DeserializeInternal(serializedAggregation[name], memberType, currentValue); // This dirty check is naive and doesn't provide performance benefits //if (memberType.IsClass && readValue != currentValue && (readValue == null || !readValue.Equals(currentValue))) _reflectionProvider.SetValue(memberInfo, instance, readValue); } catch { } } } } return(instance); }