private static Expression NewExpr(this Type baseType, Type ifInterfaceType) { var newExpr = baseType.IsInterface() ? New( ifInterfaceType.MakeGenericType(ElementTypeHelper.GetElementTypes(baseType, ElementTypeFlags.BreakKeyValuePair))) : DelegateFactory.GenerateConstructorExpression(baseType); return(newExpr); }
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 MapKeyPairValueExpr(IConfigurationProvider configurationProvider, ProfileMap profileMap, Type sourceType, Type destType, Expression contextParam, out ParameterExpression itemParam) { var sourceElementTypes = ElementTypeHelper.GetElementTypes(sourceType, ElementTypeFlags.BreakKeyValuePair); var destElementTypes = ElementTypeHelper.GetElementTypes(destType, ElementTypeFlags.BreakKeyValuePair); var typePairKey = new TypePair(sourceElementTypes[0], destElementTypes[0]); var typePairValue = new TypePair(sourceElementTypes[1], destElementTypes[1]); var sourceElementType = typeof(KeyValuePair <,>).MakeGenericType(sourceElementTypes); itemParam = Parameter(sourceElementType, "item"); var destElementType = typeof(KeyValuePair <,>).MakeGenericType(destElementTypes); var keyExpr = MapExpression(configurationProvider, profileMap, typePairKey, Property(itemParam, "Key"), contextParam); var valueExpr = MapExpression(configurationProvider, profileMap, typePairValue, Property(itemParam, "Value"), contextParam); var keyPair = New(destElementType.GetDeclaredConstructors().First(), keyExpr, valueExpr); return(keyPair); }
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)); } } }