private Expression CreatePropertyMapFunc(PropertyMap propertyMap)
{
var destMember = MakeMemberAccess(_destination, propertyMap.DestinationProperty);
Expression getter;
var pi = propertyMap.DestinationProperty as PropertyInfo;
if(pi != null && 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;
if(propertyMap.DestinationPropertyType != null)
{
var typePair = new TypePair(valueResolverExpr.Type, propertyMap.DestinationPropertyType);
valueResolverExpr = MapExpression(typePair, valueResolverExpr, propertyMap, destValueExpr);
}
else
{
valueResolverExpr = SetMap(propertyMap, valueResolverExpr, destValueExpr);
}
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);
}