namespace Unosquare.Swan.Components { using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Abstractions; /// /// Represents an object map. /// /// The type of the source. /// The type of the destination. /// public class ObjectMap : IObjectMap { internal ObjectMap(IEnumerable intersect) { SourceType = typeof(TSource); DestinationType = typeof(TDestination); Map = intersect.ToDictionary( property => DestinationType.GetProperty(property.Name), property => new List {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) { var propertyDestinationInfo = (destinationProperty.Body as MemberExpression)?.Member as PropertyInfo; if (propertyDestinationInfo == null) { throw new ArgumentException("Invalid destination expression", nameof(destinationProperty)); } var sourceMembers = GetSourceMembers(sourceProperty); if (sourceMembers.Any() == false) { throw new ArgumentException("Invalid source expression", nameof(sourceProperty)); } // reverse order sourceMembers.Reverse(); 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) { var propertyDestinationInfo = (destinationProperty.Body as MemberExpression)?.Member as PropertyInfo; if (propertyDestinationInfo == null) throw new ArgumentException("Invalid destination expression", nameof(destinationProperty)); if (Map.ContainsKey(propertyDestinationInfo)) { Map.Remove(propertyDestinationInfo); } return this; } private static List GetSourceMembers(Expression> sourceProperty) { var sourceMembers = new List(); var initialExpression = sourceProperty.Body as MemberExpression; while (true) { var propertySourceInfo = initialExpression?.Member as PropertyInfo; if (propertySourceInfo == null) break; sourceMembers.Add(propertySourceInfo); initialExpression = initialExpression.Expression as MemberExpression; } return sourceMembers; } } }