public XmlConstructorParameterTypeInfo GetOrCreateConstructorParameterTypeInfo(int constructorParameterIndex) { if (!ConstructorParametersTypeInfo.TryGetValue(constructorParameterIndex, out XmlConstructorParameterTypeInfo xmlConstructorParameterTypeInfo)) { xmlConstructorParameterTypeInfo = new XmlConstructorParameterTypeInfo(); ConstructorParametersTypeInfo.Add(constructorParameterIndex, xmlConstructorParameterTypeInfo); } return(xmlConstructorParameterTypeInfo); }
private object DeserializeObject(XElement serializedObject, Type serializedObjectType) { //todo refactor if (serializedObjectType == null) { if (!XmlDataModel.XmlModelInfo.SerializationTypesKeyedByName.TryGetValue(serializedObject.Name.LocalName, out serializedObjectType)) { string errorMessage = $"Error occurred during xml deserialization. The {serializedObject.Name.LocalName} type cannot be resolved!"; throw new SerializationException(errorMessage); } } if (ElementIsContainer(serializedObject)) { if (XmlCollectionHelper.IsSupportedCollectionType(serializedObjectType)) { IEnumerable <object> deserializedCollectionValues = DeserializeCollectionValues(serializedObject, serializedObjectType); ICollectionHelper collectionPropertyHelper = XmlCollectionHelper.Create(serializedObjectType); collectionPropertyHelper.CreateCollectionFromValues(deserializedCollectionValues, out object deserializedCollectionObject); return(deserializedCollectionObject); } if (XmlDataModel.XmlModelInfo.EntitiesInfoKeyedByType.TryGetValue(serializedObjectType, out XmlEntityTypeInfo xmlEntityTypeInfo)) { object[] constructorArgs = null; var propertiesUsedByConstructor = new Dictionary <string, (object PropertyValue, bool ShouldBeUpdatedBySerializer)>(); int constructorParametersCount = xmlEntityTypeInfo.ConstructorParametersTypeInfo.Count; if (constructorParametersCount > 0) { constructorArgs = new object[constructorParametersCount]; for (int i = 0; i < constructorParametersCount; i++) { XmlConstructorParameterTypeInfo constructorParameterTypeInfo = xmlEntityTypeInfo.ConstructorParametersTypeInfo[i]; string associatedPropertyName = constructorParameterTypeInfo.AssociatedPropertyName; if (xmlEntityTypeInfo.PropertiesTypeInfo.TryGetValue(associatedPropertyName, out XmlPropertyTypeInfo xmlPropertyTypeInfo)) { string elementName = GetXmlObjectName(xmlPropertyTypeInfo); if (xmlPropertyTypeInfo.SerializeAsXmlAttribute) { XAttribute serializedPropertyAttribute = serializedObject.Attribute(elementName); if (serializedPropertyAttribute != null) { serializedPropertyAttribute.Value.Convert(xmlPropertyTypeInfo.PropertyInfo.PropertyType, out object convertedValue); constructorArgs[i] = convertedValue; propertiesUsedByConstructor[associatedPropertyName] = (convertedValue, constructorParameterTypeInfo.AssociatedPropertyValueIsSetBySerializer); } else { throw new Exception($"Constructor argument[{i}] of type {serializedObjectType.FullName} is associated with property {associatedPropertyName} but the {elementName} attribute is not present into serialized object body"); } } else { XElement serializedPropertyElement = serializedObject.Element(elementName); if (serializedPropertyElement != null) { object deserializedObject = DeserializeObject(serializedPropertyElement, xmlPropertyTypeInfo.PropertyInfo.PropertyType); constructorArgs[i] = deserializedObject; propertiesUsedByConstructor[associatedPropertyName] = (deserializedObject, constructorParameterTypeInfo.AssociatedPropertyValueIsSetBySerializer); } else { throw new Exception($"Constructor argument[{i}] of type {serializedObjectType.FullName} is associated with property {associatedPropertyName} but the {elementName} element is not present into serialized object body"); } } } else { throw new Exception($"Constructor argument[{i}] of type {serializedObjectType.FullName} is associated with property {associatedPropertyName} but the property is not configured by model builder."); } } } object instance = Activator.CreateInstance(serializedObjectType, constructorArgs); foreach (XmlPropertyTypeInfo xmlPropertyTypeInfo in xmlEntityTypeInfo.PropertiesTypeInfo.Values) { if (propertiesUsedByConstructor.TryGetValue(xmlPropertyTypeInfo.AssociatedPropertyName, out var constructorProperty)) { if (constructorProperty.ShouldBeUpdatedBySerializer) { if (constructorProperty.PropertyValue != null && XmlCollectionHelper.IsSupportedCollectionType(xmlPropertyTypeInfo.PropertyInfo.PropertyType)) { if (xmlPropertyTypeInfo.PropertyInfo.CanRead) { object propertyValue = xmlPropertyTypeInfo.PropertyInfo.GetValue(instance, null); if (propertyValue != null) { ICollectionHelper collectionHelper = XmlCollectionHelper.Create(xmlPropertyTypeInfo.PropertyInfo.PropertyType); if (collectionHelper.TryFillCollectionValues(propertyValue, constructorProperty.PropertyValue)) { continue; } } } } ThrowIfPropertyCannotWrite(xmlPropertyTypeInfo.PropertyInfo); xmlPropertyTypeInfo.PropertyInfo.SetValue(instance, constructorProperty.PropertyValue); } else { continue; } } if (xmlPropertyTypeInfo.PropertyInfo.DeclaringType != serializedObjectType) { if (XmlDataModel.XmlModelInfo.EntitiesInfoKeyedByType.TryGetValue(xmlPropertyTypeInfo.PropertyInfo.DeclaringType, out XmlEntityTypeInfo baseEntityTypeInfo)) { XmlConstructorParameterTypeInfo baseConstructorParameterInfoAssociatedWithCurrentProperty = baseEntityTypeInfo.ConstructorParametersTypeInfo.Values.FirstOrDefault(constructorParameterInfo => constructorParameterInfo.AssociatedPropertyName == xmlPropertyTypeInfo.PropertyInfo.Name); if (baseConstructorParameterInfoAssociatedWithCurrentProperty != null && !baseConstructorParameterInfoAssociatedWithCurrentProperty.AssociatedPropertyValueIsSetBySerializer) { continue; } } } string elementName = GetXmlObjectName(xmlPropertyTypeInfo); if (xmlPropertyTypeInfo.SerializeAsXmlAttribute) { XAttribute serializedPropertyAttribute = serializedObject.Attribute(elementName); if (serializedPropertyAttribute != null) { ThrowIfPropertyCannotWrite(xmlPropertyTypeInfo.PropertyInfo); serializedPropertyAttribute.Value.Convert(xmlPropertyTypeInfo.PropertyInfo.PropertyType, out object convertedValue); xmlPropertyTypeInfo.PropertyInfo.SetValue(instance, convertedValue); } } else { XElement serializedPropertyElement = serializedObject.Element(elementName); if (serializedPropertyElement != null) { if (XmlCollectionHelper.IsSupportedCollectionType(xmlPropertyTypeInfo.PropertyInfo.PropertyType)) { IEnumerable <object> deserializedCollectionValues = DeserializeCollectionValues(serializedPropertyElement, xmlPropertyTypeInfo.PropertyInfo.PropertyType); ICollectionHelper collectionPropertyHelper = XmlCollectionHelper.Create(xmlPropertyTypeInfo.PropertyInfo.PropertyType); if (xmlPropertyTypeInfo.PropertyInfo.CanRead) { object propertyValue = xmlPropertyTypeInfo.PropertyInfo.GetValue(instance, null); if (propertyValue != null) { ICollectionHelper collectionHelper = XmlCollectionHelper.Create(xmlPropertyTypeInfo.PropertyInfo.PropertyType); if (collectionHelper.TryFillCollectionValues(propertyValue, deserializedCollectionValues)) { continue; } } } ThrowIfPropertyCannotWrite(xmlPropertyTypeInfo.PropertyInfo); collectionPropertyHelper.CreateCollectionFromValues(deserializedCollectionValues, out object createdCollectionWithValues); xmlPropertyTypeInfo.PropertyInfo.SetValue(instance, createdCollectionWithValues); continue; } ThrowIfPropertyCannotWrite(xmlPropertyTypeInfo.PropertyInfo); object deserializedObject = DeserializeObject(serializedPropertyElement, xmlPropertyTypeInfo.PropertyInfo.PropertyType); xmlPropertyTypeInfo.PropertyInfo.SetValue(instance, deserializedObject); } } } return(instance); } else { string errorMessage = $"Error occurred during xml deserialization. Unknown entity {serializedObjectType.FullName}"; throw new SerializationException(errorMessage); } } else { serializedObject.Value.Convert(serializedObjectType, out object convertedValue); return(convertedValue); } }