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;
}
}
}