public static Expression MapCollectionExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression, Func <Expression, Expression> conditionalExpression, Type ifInterfaceType, MapItem mapItem) { var passedDestination = Variable(destExpression.Type, "passedDestination"); var condition = conditionalExpression(passedDestination); var newExpression = Variable(passedDestination.Type, "collectionDestination"); var sourceElementType = ElementTypeHelper.GetElementType(sourceExpression.Type); var itemExpr = mapItem(configurationProvider, profileMap, propertyMap, sourceExpression.Type, passedDestination.Type, contextExpression, out ParameterExpression itemParam); var destinationElementType = itemExpr.Type; var destinationCollectionType = typeof(ICollection <>).MakeGenericType(destinationElementType); if (!destinationCollectionType.IsAssignableFrom(destExpression.Type)) { destinationCollectionType = typeof(IList); } var addMethod = destinationCollectionType.GetDeclaredMethod("Add"); var destination = propertyMap?.UseDestinationValue == true ? passedDestination : newExpression; var addItems = ForEach(sourceExpression, itemParam, Call(destination, addMethod, itemExpr)); var mapExpr = Block(addItems, destination); var ifNullExpr = profileMap.AllowNullCollections ? Constant(null, passedDestination.Type) : (Expression)newExpression; var clearMethod = destinationCollectionType.GetDeclaredMethod("Clear"); var isSourceNull = sourceExpression.Type.IsValueType() ? (Expression)Constant(false) : Equal(sourceExpression, Constant(null)); var checkNull = Block(new[] { newExpression, passedDestination }, Assign(passedDestination, destExpression), IfThenElse(condition ?? Constant(false), Block(Assign(newExpression, passedDestination), Call(newExpression, clearMethod)), Assign(newExpression, passedDestination.Type.NewExpr(ifInterfaceType))), Condition(isSourceNull, ToType(ifNullExpr, passedDestination.Type), ToType(mapExpr, passedDestination.Type)) ); if (propertyMap != null) { return(checkNull); } var elementTypeMap = configurationProvider.ResolveTypeMap(sourceElementType, destinationElementType); if (elementTypeMap == null) { return(checkNull); } var checkContext = TypeMapPlanBuilder.CheckContext(elementTypeMap, contextExpression); if (checkContext == null) { return(checkNull); } return(Block(checkContext, checkNull)); }
public static Expression MapItemExpr(IConfigurationProvider configurationProvider, ProfileMap profileMap, Type sourceType, Type destType, Expression contextParam, out ParameterExpression itemParam) { var sourceElementType = ElementTypeHelper.GetElementType(sourceType); var destElementType = ElementTypeHelper.GetElementType(destType); itemParam = Parameter(sourceElementType, "item"); var typePair = new TypePair(sourceElementType, destElementType); var itemExpr = MapExpression(configurationProvider, profileMap, typePair, itemParam, contextParam); return(ToType(itemExpr, destElementType)); }
public static Expression MapCollectionExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression, Type ifInterfaceType, MapItem mapItem) { var passedDestination = Variable(destExpression.Type, "passedDestination"); var newExpression = Variable(passedDestination.Type, "collectionDestination"); var sourceElementType = ElementTypeHelper.GetElementType(sourceExpression.Type); var itemExpr = mapItem(configurationProvider, profileMap, sourceExpression.Type, passedDestination.Type, contextExpression, out ParameterExpression itemParam); var destinationElementType = itemExpr.Type; var destinationCollectionType = typeof(ICollection <>).MakeGenericType(destinationElementType); if (!destinationCollectionType.IsAssignableFrom(destExpression.Type)) { destinationCollectionType = typeof(IList); } var addMethod = destinationCollectionType.GetDeclaredMethod("Add"); Expression destination, createInstance, assignNewExpression; UseDestinationValue(); var addItems = ForEach(sourceExpression, itemParam, Call(destination, addMethod, itemExpr)); var mapExpr = Block(addItems, destination); var clearMethod = destinationCollectionType.GetDeclaredMethod("Clear"); var checkNull = Block(new[] { newExpression, passedDestination }, Assign(passedDestination, destExpression), assignNewExpression, Call(destination, clearMethod), ToType(mapExpr, createInstance.Type) ); if (propertyMap != null) { return(checkNull); } var elementTypeMap = configurationProvider.ResolveTypeMap(sourceElementType, destinationElementType); if (elementTypeMap == null) { return(checkNull); } var checkContext = CheckContext(elementTypeMap, contextExpression); if (checkContext == null) { return(checkNull); } return(Block(checkContext, checkNull)); void UseDestinationValue() { if (propertyMap?.UseDestinationValue == true) { createInstance = passedDestination; destination = passedDestination; assignNewExpression = Empty(); } else { destination = newExpression; createInstance = passedDestination.Type.NewExpr(ifInterfaceType); var isReadOnly = Property(ToType(passedDestination, destinationCollectionType), "IsReadOnly"); assignNewExpression = Assign(newExpression, Condition(OrElse(Equal(passedDestination, Constant(null)), isReadOnly), ToType(createInstance, passedDestination.Type), passedDestination)); } } }