tools/AutoMapper/PropertyMap.cs (125 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using AutoMapper.Configuration;
namespace AutoMapper
{
using static Expression;
[DebuggerDisplay("{DestinationProperty.Name}")]
public class PropertyMap
{
private readonly List<MemberInfo> _memberChain = new List<MemberInfo>();
private readonly List<ValueTransformerConfiguration> _valueTransformerConfigs = new List<ValueTransformerConfiguration>();
public PropertyMap(PathMap pathMap)
{
Condition = pathMap.Condition;
DestinationProperty = pathMap.DestinationMember;
CustomExpression = pathMap.SourceExpression;
TypeMap = pathMap.TypeMap;
}
public PropertyMap(MemberInfo destinationProperty, TypeMap typeMap)
{
TypeMap = typeMap;
DestinationProperty = destinationProperty;
}
public PropertyMap(PropertyMap inheritedMappedProperty, TypeMap typeMap)
: this(inheritedMappedProperty.DestinationProperty, typeMap)
{
ApplyInheritedPropertyMap(inheritedMappedProperty);
}
public TypeMap TypeMap { get; }
public MemberInfo DestinationProperty { get; }
public Type DestinationPropertyType => DestinationProperty.GetMemberType();
public ICollection<MemberInfo> SourceMembers => _memberChain;
public bool Inline { get; set; } = true;
public bool Ignored { get; set; }
public bool AllowNull { get; set; }
public int? MappingOrder { get; set; }
public LambdaExpression CustomResolver { get; set; }
public LambdaExpression Condition { get; set; }
public LambdaExpression PreCondition { get; set; }
public LambdaExpression CustomExpression { get; set; }
public bool UseDestinationValue { get; set; }
public bool ExplicitExpansion { get; set; }
public object NullSubstitute { get; set; }
public ValueResolverConfiguration ValueResolverConfig { get; set; }
public IEnumerable<ValueTransformerConfiguration> ValueTransformers => _valueTransformerConfigs;
public string CustomSourceMemberName { get; set; }
public MemberInfo SourceMember
{
get
{
if (CustomSourceMemberName != null)
return TypeMap.SourceType.GetFieldOrProperty(CustomSourceMemberName);
if (CustomExpression != null)
{
var finder = new MemberFinderVisitor();
finder.Visit(CustomExpression);
if (finder.Member != null)
{
return finder.Member.Member;
}
}
return _memberChain.LastOrDefault();
}
}
public Type SourceType
{
get
{
if (CustomExpression != null)
return CustomExpression.ReturnType;
if (CustomResolver != null)
return CustomResolver.ReturnType;
if(ValueResolverConfig != null)
return typeof(object);
return SourceMember?.GetMemberType();
}
}
public void ChainMembers(IEnumerable<MemberInfo> members)
{
var getters = members as IList<MemberInfo> ?? members.ToList();
_memberChain.AddRange(getters);
}
public void ApplyInheritedPropertyMap(PropertyMap inheritedMappedProperty)
{
if(inheritedMappedProperty.Ignored && !ResolveConfigured())
{
Ignored = true;
}
CustomExpression = CustomExpression ?? inheritedMappedProperty.CustomExpression;
CustomResolver = CustomResolver ?? inheritedMappedProperty.CustomResolver;
Condition = Condition ?? inheritedMappedProperty.Condition;
PreCondition = PreCondition ?? inheritedMappedProperty.PreCondition;
NullSubstitute = NullSubstitute ?? inheritedMappedProperty.NullSubstitute;
MappingOrder = MappingOrder ?? inheritedMappedProperty.MappingOrder;
ValueResolverConfig = ValueResolverConfig ?? inheritedMappedProperty.ValueResolverConfig;
CustomSourceMemberName = CustomSourceMemberName ?? inheritedMappedProperty.CustomSourceMemberName;
}
public bool IsMapped() => HasSource() || Ignored;
public bool CanResolveValue() => HasSource() && !Ignored;
public bool HasSource() => _memberChain.Count > 0 || ResolveConfigured();
public bool ResolveConfigured() => ValueResolverConfig != null || CustomResolver != null || CustomExpression != null || CustomSourceMemberName != null;
public void MapFrom(LambdaExpression sourceMember)
{
CustomExpression = sourceMember;
Ignored = false;
}
public void AddValueTransformation(ValueTransformerConfiguration valueTransformerConfiguration)
{
_valueTransformerConfigs.Add(valueTransformerConfiguration);
}
private class MemberFinderVisitor : ExpressionVisitor
{
public MemberExpression Member { get; private set; }
protected override Expression VisitMember(MemberExpression node)
{
Member = node;
return base.VisitMember(node);
}
}
}
}