in tools/AutoMapper/Execution/TypeMapPlanBuilder.cs [379:471]
private Expression CreatePropertyMapFunc(PropertyMap propertyMap, Expression destination)
{
var destMember = MakeMemberAccess(destination, propertyMap.DestinationProperty);
Expression getter;
if (propertyMap.DestinationProperty is PropertyInfo pi && pi.GetGetMethod(true) == null)
getter = Default(propertyMap.DestinationPropertyType);
else
getter = destMember;
Expression destValueExpr;
if (propertyMap.UseDestinationValue)
{
destValueExpr = getter;
}
else
{
if (_initialDestination.Type.IsValueType())
destValueExpr = Default(propertyMap.DestinationPropertyType);
else
destValueExpr = Condition(Equal(_initialDestination, Constant(null)),
Default(propertyMap.DestinationPropertyType), getter);
}
var valueResolverExpr = BuildValueResolverFunc(propertyMap, getter);
var resolvedValue = Variable(valueResolverExpr.Type, "resolvedValue");
var setResolvedValue = Assign(resolvedValue, valueResolverExpr);
valueResolverExpr = resolvedValue;
var typePair = new TypePair(valueResolverExpr.Type, propertyMap.DestinationPropertyType);
valueResolverExpr = propertyMap.Inline
? MapExpression(_configurationProvider, _typeMap.Profile, typePair, valueResolverExpr, Context,
propertyMap, destValueExpr)
: ContextMap(typePair, valueResolverExpr, Context, destValueExpr);
valueResolverExpr = propertyMap.ValueTransformers
.Concat(_typeMap.ValueTransformers)
.Concat(_typeMap.Profile.ValueTransformers)
.Where(vt => vt.IsMatch(propertyMap))
.Aggregate(valueResolverExpr, (current, vtConfig) => ToType(ReplaceParameters(vtConfig.TransformerExpression, ToType(current, vtConfig.ValueType)), propertyMap.DestinationPropertyType));
ParameterExpression propertyValue;
Expression setPropertyValue;
if (valueResolverExpr == resolvedValue)
{
propertyValue = resolvedValue;
setPropertyValue = setResolvedValue;
}
else
{
propertyValue = Variable(valueResolverExpr.Type, "propertyValue");
setPropertyValue = Assign(propertyValue, valueResolverExpr);
}
Expression mapperExpr;
if (propertyMap.DestinationProperty is FieldInfo)
{
mapperExpr = propertyMap.SourceType != propertyMap.DestinationPropertyType
? Assign(destMember, ToType(propertyValue, propertyMap.DestinationPropertyType))
: Assign(getter, propertyValue);
}
else
{
var setter = ((PropertyInfo) propertyMap.DestinationProperty).GetSetMethod(true);
if (setter == null)
mapperExpr = propertyValue;
else
mapperExpr = Assign(destMember, ToType(propertyValue, propertyMap.DestinationPropertyType));
}
if (propertyMap.Condition != null)
mapperExpr = IfThen(
propertyMap.Condition.ConvertReplaceParameters(
Source,
_destination,
ToType(propertyValue, propertyMap.Condition.Parameters[2].Type),
ToType(getter, propertyMap.Condition.Parameters[2].Type),
Context
),
mapperExpr
);
mapperExpr = Block(new[] {setResolvedValue, setPropertyValue, mapperExpr}.Distinct());
if (propertyMap.PreCondition != null)
mapperExpr = IfThen(
propertyMap.PreCondition.ConvertReplaceParameters(Source, Context),
mapperExpr
);
return Block(new[] {resolvedValue, propertyValue}.Distinct(), mapperExpr);
}