using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace Swan.Mappers { /// /// Represents an object map. /// /// The type of the source. /// The type of the destination. /// public class ObjectMap : IObjectMap { internal ObjectMap(IEnumerable intersect) { this.SourceType = typeof(TSource); this.DestinationType = typeof(TDestination); this.Map = intersect.ToDictionary(property => this.DestinationType.GetProperty(property.Name), property => new List { this.SourceType.GetProperty(property.Name) }); } /// public Dictionary> Map { get; } /// public Type SourceType { get; } /// public Type DestinationType { get; } /// /// Maps the property. /// /// The type of the destination property. /// The type of the source property. /// The destination property. /// The source property. /// /// An object map representation of type of the destination property /// and type of the source property. /// public ObjectMap MapProperty(Expression> destinationProperty, Expression> sourceProperty) { PropertyInfo propertyDestinationInfo = (destinationProperty.Body as MemberExpression)?.Member as PropertyInfo; if(propertyDestinationInfo == null) { throw new ArgumentException("Invalid destination expression", nameof(destinationProperty)); } List sourceMembers = GetSourceMembers(sourceProperty); if(sourceMembers.Any() == false) { throw new ArgumentException("Invalid source expression", nameof(sourceProperty)); } // reverse order sourceMembers.Reverse(); this.Map[propertyDestinationInfo] = sourceMembers; return this; } /// /// Removes the map property. /// /// The type of the destination property. /// The destination property. /// /// An object map representation of type of the destination property /// and type of the source property. /// /// Invalid destination expression. public ObjectMap RemoveMapProperty(Expression> destinationProperty) { PropertyInfo propertyDestinationInfo = (destinationProperty.Body as MemberExpression)?.Member as PropertyInfo; if(propertyDestinationInfo == null) { throw new ArgumentException("Invalid destination expression", nameof(destinationProperty)); } if(this.Map.ContainsKey(propertyDestinationInfo)) { _ = this.Map.Remove(propertyDestinationInfo); } return this; } private static List GetSourceMembers(Expression> sourceProperty) { List sourceMembers = new List(); MemberExpression initialExpression = sourceProperty.Body as MemberExpression; while(true) { PropertyInfo propertySourceInfo = initialExpression?.Member as PropertyInfo; if(propertySourceInfo == null) { break; } sourceMembers.Add(propertySourceInfo); initialExpression = initialExpression.Expression as MemberExpression; } return sourceMembers; } } }