RaspberryIO_26/Swan.Lite/Mappers/ObjectMap.cs

116 lines
4.4 KiB
C#
Raw Normal View History

2019-12-04 18:57:18 +01:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Swan.Mappers
{
/// <summary>
/// Represents an object map.
/// </summary>
/// <typeparam name="TSource">The type of the source.</typeparam>
/// <typeparam name="TDestination">The type of the destination.</typeparam>
/// <seealso cref="IObjectMap" />
public class ObjectMap<TSource, TDestination> : IObjectMap
{
internal ObjectMap(IEnumerable<PropertyInfo> intersect)
{
SourceType = typeof(TSource);
DestinationType = typeof(TDestination);
Map = intersect.ToDictionary(
property => DestinationType.GetProperty(property.Name),
property => new List<PropertyInfo> {SourceType.GetProperty(property.Name)});
}
/// <inheritdoc/>
public Dictionary<PropertyInfo, List<PropertyInfo>> Map { get; }
/// <inheritdoc/>
public Type SourceType { get; }
/// <inheritdoc/>
public Type DestinationType { get; }
/// <summary>
/// Maps the property.
/// </summary>
/// <typeparam name="TDestinationProperty">The type of the destination property.</typeparam>
/// <typeparam name="TSourceProperty">The type of the source property.</typeparam>
/// <param name="destinationProperty">The destination property.</param>
/// <param name="sourceProperty">The source property.</param>
/// <returns>
/// An object map representation of type of the destination property
/// and type of the source property.
/// </returns>
public ObjectMap<TSource, TDestination> MapProperty
<TDestinationProperty, TSourceProperty>(
Expression<Func<TDestination, TDestinationProperty>> destinationProperty,
Expression<Func<TSource, TSourceProperty>> 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;
}
/// <summary>
/// Removes the map property.
/// </summary>
/// <typeparam name="TDestinationProperty">The type of the destination property.</typeparam>
/// <param name="destinationProperty">The destination property.</param>
/// <returns>
/// An object map representation of type of the destination property
/// and type of the source property.
/// </returns>
/// <exception cref="System.Exception">Invalid destination expression.</exception>
public ObjectMap<TSource, TDestination> RemoveMapProperty<TDestinationProperty>(
Expression<Func<TDestination, TDestinationProperty>> 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<PropertyInfo> GetSourceMembers<TSourceProperty>(Expression<Func<TSource, TSourceProperty>> sourceProperty)
{
var sourceMembers = new List<PropertyInfo>();
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;
}
}
}