object DeserializeClass(object inInstance, IKey inKey, Type type, int inStructDeep, ILogPrinter inLogger) { IKey type_key = inKey.GetChild("RealObjectType"); if (type_key != null) { string type_name = type_key.GetValueAsString(0); string assembly_name = type_key.GetValueAsString(1); try { Assembly assembly = Assembly.Load(assembly_name); Type obj_type = assembly.GetType(type_name, true); if (obj_type != null) { type = obj_type; } } catch (Exception ex) { LogError(inLogger, string.Format("Cant take type from RealObjectType {0}. Exception: {1}", type_name, ex.Message)); } } object instance = inInstance; if (instance == null) { instance = _reflectionProvider.Instantiate(type, inLogger); } if (instance != null) { //MethodInfo mi = type.GetMethod("DeserializationFromCscd", new Type[] { typeof(CascadeParser.IKey), typeof(CascadeParser.ILogPrinter) }); MethodInfo mi = type.GetMethod("DeserializationFromCscd", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (mi != null) { if (inKey != null && !inKey.IsEmpty) { IKey key = inKey; mi.Invoke(instance, new object[] { key, inLogger }); } } else { MemberInfo[] member_infos = _reflectionProvider.GetSerializableMembers(type); foreach (MemberInfo memberInfo in member_infos) { SCustomMemberParams member_params = GetMemberParams(memberInfo); Type memberType = memberInfo.GetMemberType(); IKey sub_key = inKey.GetChild(member_params.ChangedName); if (sub_key == null) { sub_key = inKey.GetChild(member_params.Name); } if (sub_key != null) { object readValue; if (member_params.Converter != null) { readValue = member_params.Converter.ReadKey(sub_key, inLogger); } else { readValue = DeserializeInternal(null, sub_key, memberType, 0, inStructDeep + 1, inLogger); } // 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, inLogger); } else if (member_params.DefaultValue != null) { _reflectionProvider.SetValue(memberInfo, instance, member_params.DefaultValue, inLogger); } else if (memberType.IsClass || memberType.IsStruct()) { object already_exists_member = _reflectionProvider.GetValue(memberInfo, instance); if (already_exists_member != null) { //for set default values inside this object already_exists_member = DeserializeInternal(already_exists_member, IKeyFactory.CreateKey(string.Empty), memberType, 0, inStructDeep + 1, inLogger); if (already_exists_member != null) { _reflectionProvider.SetValue(memberInfo, instance, already_exists_member, inLogger); } } } } } mi = type.GetMethod("OnDeserializedMethod", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (mi != null) { var context = new StreamingContext(StreamingContextStates.Other); mi.Invoke(instance, new object[] { context }); } } return(instance); }
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); }