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 = Expression.Parameter(sourceElementType, "item"); var typePair = new TypePair(sourceElementType, destElementType); var itemExpr = ExpressionBuilder.MapExpression(configurationProvider, profileMap, typePair, itemParam, contextParam); return(ExpressionFactory.ToType(itemExpr, destElementType)); }
public static Expression MapCollectionExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap, IMemberMap memberMap, Expression sourceExpression, Expression destExpression, Expression contextExpression, Type ifInterfaceType, MapItem mapItem) { var passedDestination = Expression.Variable(destExpression.Type, "passedDestination"); var newExpression = Expression.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, assignNewExpression; UseDestinationValue(); var addItems = ExpressionFactory.ForEach(sourceExpression, itemParam, Expression.Call(destination, addMethod, itemExpr)); var mapExpr = Expression.Block(addItems, destination); var clearMethod = destinationCollectionType.GetDeclaredMethod("Clear"); var checkNull = Expression.Block(new[] { newExpression, passedDestination }, Expression.Assign(passedDestination, destExpression), assignNewExpression, Expression.Call(destination, clearMethod), mapExpr ); if (memberMap != null) { return(checkNull); } var elementTypeMap = configurationProvider.ResolveTypeMap(sourceElementType, destinationElementType); if (elementTypeMap == null) { return(checkNull); } var checkContext = ExpressionBuilder.CheckContext(elementTypeMap, contextExpression); if (checkContext == null) { return(checkNull); } return(Expression.Block(checkContext, checkNull)); void UseDestinationValue() { if (memberMap?.UseDestinationValue == true) { destination = passedDestination; assignNewExpression = Expression.Empty(); } else { destination = newExpression; Expression createInstance = passedDestination.Type.NewExpr(ifInterfaceType); var isReadOnly = Expression.Property(ExpressionFactory.ToType(passedDestination, destinationCollectionType), "IsReadOnly"); assignNewExpression = Expression.Assign(newExpression, Expression.Condition(Expression.OrElse(Expression.Equal(passedDestination, Expression.Constant(null)), isReadOnly), ExpressionFactory.ToType(createInstance, passedDestination.Type), passedDestination)); } } }