private IEnumerable <object> DeserializeCollectionValues(XElement serializedCollectionObject, Type collectionType) { foreach (XElement serializedCollectionItem in serializedCollectionObject.Elements()) { if (serializedCollectionItem.Name.LocalName == "Collection") { Type collectionItemType = GetCollectionItemType(collectionType); IEnumerable <object> deserializedCollectionValues = DeserializeCollectionValues(serializedCollectionItem, collectionItemType); ICollectionHelper collectionHelper; if (collectionItemType == typeof(object)) { collectionHelper = XmlCollectionHelper.Create(typeof(List <object>)); } else { collectionHelper = XmlCollectionHelper.Create(collectionItemType); } collectionHelper.CreateCollectionFromValues(deserializedCollectionValues, out object deserializedCollectionObject); yield return(deserializedCollectionObject); } else { object deserializedObject = DeserializeObject(serializedCollectionItem, null); yield return(deserializedObject); } } }
/// <summary> /// Returns an object that can be used to configure a property of the entity type. /// If the specified property is not already part of the model, it will be added. /// </summary> /// <typeparam name="T">The type of the property to be configured.</typeparam> /// <param name="propertyExpression">A lambda expression representing the property to be configured ( blog => blog.Url).</param> /// <returns><see cref="XmlPropertyTypeBuilder{TEntity,TProperty}"/>An object that can be used to configure the property.</returns> public XmlPropertyTypeBuilder <TEntity, T> Property <T>(Expression <Func <TEntity, T> > propertyExpression) { ExpressionHelper.GetPropertyInfo(propertyExpression, out string propertyName, out PropertyInfo propertyInfo); if (propertyInfo.PropertyType.IsInterface && !XmlCollectionHelper.IsSupportedCollectionType(propertyInfo.PropertyType)) { throw new InvalidOperationException($"Serialization/deserialization from interfaces is not allowd. Property:{propertyInfo.DeclaringType.Name}.{propertyName} of type:{propertyInfo.PropertyType.Name}. Choose a concrete type for selected property."); } XmlPropertyTypeInfo xmlPropertyTypeInfo = _xmlEntityTypeInfo.GetOrCreatePropertyTypeInfo(propertyName, propertyInfo); return(new XmlPropertyTypeBuilder <TEntity, T>(_xmlEntityTypeInfo, xmlPropertyTypeInfo, _xmlModelTypeInfo, _xmlModelTypeBuilder)); }
private XElement SerializeObject(object objectToBeSerialized, string objectName) { if (objectToBeSerialized == null) { throw new ArgumentNullException(nameof(objectToBeSerialized)); } Type objectToBeSerializedType = objectToBeSerialized.GetType(); XElement serializedObject = new XElement("Object"); if (XmlCollectionHelper.IsSupportedCollectionType(objectToBeSerializedType)) { if (objectName == null) { objectName = "Collection"; } IEnumerable objectToBeSerializedCollection = (IEnumerable)objectToBeSerialized; foreach (object collectionValue in objectToBeSerializedCollection) { if (collectionValue != null) { XElement serializedCollectionValue = SerializeObject(collectionValue, null); if (!IsEmptyCollectionNode(serializedCollectionValue)) { serializedObject.Add(serializedCollectionValue); } } } } else { if (objectName == null) { objectName = GetSerializationName(objectToBeSerializedType); } if (XmlDataModel.XmlModelInfo.EntitiesInfoKeyedByType.TryGetValue(objectToBeSerializedType, out XmlEntityTypeInfo xmlEntityTypeInfo)) { foreach (XmlPropertyTypeInfo xmlPropertyTypeInfo in xmlEntityTypeInfo.PropertiesTypeInfo.Values) { PropertyInfo propertyInfo = objectToBeSerializedType.GetProperty(xmlPropertyTypeInfo.AssociatedPropertyName); object propertyValue = propertyInfo.GetValue(objectToBeSerialized, null); if (propertyValue != null) { string propertyName = propertyInfo.Name; if (!string.IsNullOrWhiteSpace(xmlPropertyTypeInfo.XmlName)) { propertyName = xmlPropertyTypeInfo.XmlName; } Type propertyValueType = propertyValue.GetType(); if (propertyValueType.IsValueType) { if (xmlPropertyTypeInfo.ShouldNotBeSerializedIfHasDefaultValue) { if (ValueIsEqualWithDefaultValueOfType(propertyValueType, propertyValue)) { continue; } } } if (xmlPropertyTypeInfo.SerializeAsXmlAttribute) { propertyValue.Convert(out string serializedValue); XAttribute propertyAttribute = new XAttribute(propertyName, serializedValue); serializedObject.Add(propertyAttribute); } else { XElement serializedProperty = SerializeObject(propertyValue, propertyName); if (!IsEmptyCollectionNode(serializedProperty)) { serializedObject.Add(serializedProperty); } } } } } if (!ElementIsContainer(serializedObject)) { objectToBeSerialized.Convert(out string instanceToBeSerializedValue); serializedObject.Value = instanceToBeSerializedValue; } } serializedObject.Name = objectName; return(serializedObject); }
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); } }