void INanoSerializable.Deserialize(IDataAdapter data, ISubDeserializer subDeserializer) { A = data.GetStringValue("1", true); object b = null; subDeserializer.ContinueDeserialization(typeof(object), data.GetChild("1").GetChild("2"), ref b); B = b; }
/// <summary> /// Deserialize object from source data. /// </summary> /// <typeparam name="T">Type of the class to deserialize root. Use <see cref="object"/> if class is unknown.</typeparam> /// <param name="data">Data source to deserialize from</param> /// <returns>The object or root of object model deserialized from <paramref name="data"/>.</returns> /// <exception cref="SerializationException">thrown when deserialization fails</exception> public T DeserializeObject <T>(IDataAdapter data) { maxObjId = 1; objectCache.Clear(); flags = (OptimizationFlags)data.GetIntValue(ATTRIBUTE_FLAGS, true); IDataAdapter types = data.GetChild(ELEMENT_TYPES); if (types != null) { IDataArray array = types.GetArray(); int index = 1; foreach (IDataAdapter child in array.GetChildren()) { typeCache.Add(index++, InternalResolveTypes(child.GetStringValue())); } } return((T)DeserializeObject(typeof(T), data, null)); }
private void FillObject(TypeWrapper wrapper, object target, IDataAdapter data) { if (wrapper.IsSelfSerializable) { ((INanoSerializable)target).Deserialize(data, this); return; } // read properties for (int i = 0; i < wrapper.Properties.Count; i++) { PropertyWrapper property = wrapper.Properties[i]; // should be already loaded at this time if (property.ConstructorArg != -1 && property.State != NanoState.SerializeSet) { continue; } if (property.Info.GetMethod.IsPrivate && property.Info.SetMethod.IsPrivate && (flags & OptimizationFlags.PrivateProperties) == 0) { continue; } if (property.TypeCategory == TypeCategory.Primitive || property.TypeCategory == TypeCategory.Enum) { if (!property.Info.CanWrite) { continue; } property.SetValue( target, DeserializePrimitive( property.MemberType, data, property.Name, property.Location != NanoLocation.SubNode, (flags & OptimizationFlags.EnumAsValue) != 0 ) ); } else { IDataAdapter subnode = data.GetChild(property.Name); if (subnode != null) { object currentValue = property.GetValue(target); if (currentValue == null) { property.SetValue(target, DeserializeObject(property.MemberType, subnode, null)); } else { DeserializeObject(property.MemberType, subnode, currentValue); } } } } // read fields for (int i = 0; i < wrapper.Fields.Count; i++) { FieldWrapper field = wrapper.Fields[i]; // should be already loaded at this time if (field.ConstructorArg != -1 && field.State != NanoState.SerializeSet) { continue; } if (field.TypeCategory == TypeCategory.Primitive || field.TypeCategory == TypeCategory.Enum) { field.SetValue( target, DeserializePrimitive( field.MemberType, data, field.Name, field.Location != NanoLocation.SubNode, (flags & OptimizationFlags.EnumAsValue) != 0 ) ); } else { IDataAdapter subnode = data.GetChild(field.Name); if (subnode != null) { object value = DeserializeObject(field.MemberType, subnode, null); if (value != null) { field.SetValue(target, value); } } } } }
private object DeserializeObject(Type type, IDataAdapter data, object target) { // existing object TypeCategory category; if (target != null) { type = target.GetType(); if ((flags & OptimizationFlags.NoContainers) == 0) { category = GetTypeCategory(type); if (category != TypeCategory.Unknown) { DeserializeContainer(type, category, data, ref target); return(target); } } FillObject(TypeCache.GetWrapper(type), target, data); return(target); } // resolve reference, if any if (type.IsClass && (flags & OptimizationFlags.NoReferences) == 0) { int id = (int)data.GetIntValue(ATTRIBUTE_OBJID, true); if (id > 0) { return(objectCache[id]); } } // fix type, if needed int typeId = (int)data.GetIntValue(ATTRIBUTE_TYPE, true); if (typeId > 0) { if (!typeCache.TryGetValue(typeId, out type)) { throw new SerializationException($"Unable to find type {typeId}"); } } // primitive type? if (IsPrimitive(type)) { return(DeserializePrimitive(type, data, (flags & OptimizationFlags.EnumAsValue) != 0)); } if ((flags & OptimizationFlags.NoContainers) == 0) { // load container category = GetTypeCategory(type); if (category != TypeCategory.Unknown) { DeserializeContainer(type, category, data, ref target); if ((flags & OptimizationFlags.NoReferences) == 0) { objectCache.Add(maxObjId++, target); } return(target); } } // this is unknown object TypeWrapper wrapper = TypeCache.GetWrapper(type); if (wrapper.Serializer != null) { return(wrapper.Serializer.DeserializeObject(data, this)); } object[] constructorArgs = null; for (int i = 0; i < wrapper.Properties.Count; i++) { PropertyWrapper property = wrapper.Properties[i]; if (property.ConstructorArg == -1) { continue; } object value = null; if (property.TypeCategory == TypeCategory.Primitive || property.TypeCategory == TypeCategory.Enum) { value = DeserializePrimitive( property.MemberType, data, property.Name, property.Location != NanoLocation.SubNode, (flags & OptimizationFlags.EnumAsValue) != 0 ); } else { IDataAdapter subnode = data.GetChild(property.Name); if (subnode != null) { value = DeserializeObject(property.MemberType, subnode, null); } } if (constructorArgs == null) { constructorArgs = new object[wrapper.ConstructorArgsCount]; } constructorArgs[property.ConstructorArg] = value; } for (int i = 0; i < wrapper.Fields.Count; i++) { FieldWrapper field = wrapper.Fields[i]; if (field.ConstructorArg == -1) { continue; } object value = null; if (field.TypeCategory == TypeCategory.Primitive || field.TypeCategory == TypeCategory.Enum) { value = DeserializePrimitive( field.MemberType, data, field.Name, field.Location != NanoLocation.SubNode, (flags & OptimizationFlags.EnumAsValue) != 0 ); } else { IDataAdapter subnode = data.GetChild(field.Name); if (subnode != null) { value = DeserializeObject(field.MemberType, subnode, null); } } if (constructorArgs == null) { constructorArgs = new object[wrapper.ConstructorArgsCount]; } constructorArgs[field.ConstructorArg] = value; } // create object target = CreateObject(wrapper, constructorArgs); if ((flags & OptimizationFlags.NoReferences) == 0) { objectCache[maxObjId++] = target; } FillObject(wrapper, target, data); return(target); }