private Expression CreatePropertyMapFunc()

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