public object Map(ResolutionContext context, IMappingEngineRunner mapper) { var sourceDelegateType = context.SourceType.GetGenericArguments()[0]; var destDelegateType = context.DestinationType.GetGenericArguments()[0]; var expression = (LambdaExpression)context.SourceValue; if (sourceDelegateType.GetGenericTypeDefinition() != destDelegateType.GetGenericTypeDefinition()) { throw new AutoMapperMappingException("Source and destination expressions must be of the same type."); } var destArgType = destDelegateType.GetGenericArguments()[0]; if (destArgType.IsGenericType()) { destArgType = destArgType.GetGenericArguments()[0]; } var sourceArgType = sourceDelegateType.GetGenericArguments()[0]; if (sourceArgType.IsGenericType()) { sourceArgType = sourceArgType.GetGenericArguments()[0]; } var typeMap = Mapper.FindTypeMapFor(destArgType, sourceArgType); var parentMasterVisitor = new MappingVisitor(destDelegateType.GetGenericArguments()); var typeMapVisitor = new MappingVisitor(typeMap, expression.Parameters[0], Expression.Parameter(destDelegateType.GetGenericArguments()[0], expression.Parameters[0].Name), parentMasterVisitor, destDelegateType.GetGenericArguments()); // Map expression body and variable seperately var parameters = expression.Parameters.Select(typeMapVisitor.Visit).OfType <ParameterExpression>(); var body = typeMapVisitor.Visit(expression.Body); return(Expression.Lambda(body, parameters)); }
public object Map(ResolutionContext context, IMappingEngineRunner mapper) { var sourceDelegateType = context.SourceType.GetGenericArguments()[0]; var destDelegateType = context.DestinationType.GetGenericArguments()[0]; var expression = (LambdaExpression) context.SourceValue; if (sourceDelegateType.GetGenericTypeDefinition() != destDelegateType.GetGenericTypeDefinition()) throw new AutoMapperMappingException("Source and destination expressions must be of the same type."); var parameters = expression.Parameters.ToArray(); var body = expression.Body; for (int i = 0; i < expression.Parameters.Count; i++) { var sourceParamType = sourceDelegateType.GetGenericArguments()[i]; var destParamType = destDelegateType.GetGenericArguments()[i]; if (sourceParamType == destParamType) continue; var typeMap = mapper.ConfigurationProvider.ResolveTypeMap(destParamType, sourceParamType); if (typeMap == null) throw new AutoMapperMappingException( $"Could not find type map from destination type {destParamType} to source type {sourceParamType}. Use CreateMap to create a map from the source to destination types."); var oldParam = expression.Parameters[i]; var newParam = Expression.Parameter(typeMap.SourceType, oldParam.Name); parameters[i] = newParam; var visitor = new MappingVisitor(typeMap, oldParam, newParam); body = visitor.Visit(body); } return Expression.Lambda(body, parameters); }
public static TDestination Map<TSource, TDestination>(TSource expression, ResolutionContext context) where TSource : LambdaExpression where TDestination : LambdaExpression { var sourceDelegateType = typeof(TSource).GetTypeInfo().GenericTypeArguments[0]; var destDelegateType = typeof(TDestination).GetTypeInfo().GenericTypeArguments[0]; if (sourceDelegateType.GetGenericTypeDefinition() != destDelegateType.GetGenericTypeDefinition()) throw new AutoMapperMappingException("Source and destination expressions must be of the same type.", null, new TypePair(typeof(TSource), typeof(TDestination))); var destArgType = destDelegateType.GetTypeInfo().GenericTypeArguments[0]; if (destArgType.IsGenericType()) destArgType = destArgType.GetTypeInfo().GenericTypeArguments[0]; var sourceArgType = sourceDelegateType.GetTypeInfo().GenericTypeArguments[0]; if (sourceArgType.IsGenericType()) sourceArgType = sourceArgType.GetTypeInfo().GenericTypeArguments[0]; var typeMap = context.ConfigurationProvider.ResolveTypeMap(destArgType, sourceArgType); var parentMasterVisitor = new MappingVisitor(context.ConfigurationProvider, destDelegateType.GetTypeInfo().GenericTypeArguments); var typeMapVisitor = new MappingVisitor(context.ConfigurationProvider, typeMap, expression.Parameters[0], Expression.Parameter(destDelegateType.GetTypeInfo().GenericTypeArguments[0], expression.Parameters[0].Name), parentMasterVisitor, destDelegateType.GetTypeInfo().GenericTypeArguments); // Map expression body and variable seperately var parameters = expression.Parameters.Select(typeMapVisitor.Visit).OfType<ParameterExpression>(); var body = typeMapVisitor.Visit(expression.Body); return (TDestination)Expression.Lambda(body, parameters); }
internal MappingVisitor(IConfigurationProvider configurationProvider, TypeMap typeMap, Expression oldParam, Expression newParam, MappingVisitor parentMappingVisitor = null, IList<Type> destSubTypes = null) { _configurationProvider = configurationProvider; _typeMap = typeMap; _oldParam = oldParam; _newParam = newParam; _parentMappingVisitor = parentMappingVisitor; if(destSubTypes != null) _destSubTypes = destSubTypes; }
internal MappingVisitor(TypeMap typeMap, Expression oldParam, Expression newParam, MappingVisitor parentMappingVisitor = null, IList <Type> destSubTypes = null) { _typeMap = typeMap; _oldParam = oldParam; _newParam = newParam; _parentMappingVisitor = parentMappingVisitor; if (destSubTypes != null) { _destSubTypes = destSubTypes; } }
protected override Expression VisitBinary(BinaryExpression node) { var newLeft = Visit(node.Left); var newRight = Visit(node.Right); if (newLeft.Type != newRight.Type) { if (ReflectionHelper.CanImplicitConvert(newRight.Type, newLeft.Type)) { newRight = ExpressionFactory.ToType(newRight, newLeft.Type); } else if (ReflectionHelper.CanImplicitConvert(newLeft.Type, newRight.Type)) { newLeft = ExpressionFactory.ToType(newLeft, newRight.Type); } else { var typeMap = _configurationProvider.ResolveTypeMap(newRight.Type, newLeft.Type); if (typeMap != null) { var visitor = new MappingVisitor(_configurationProvider, typeMap, newRight, newLeft, this); newRight = visitor.Visit(newRight); } else { // check if the non-string expression is a null constent // as this would lead to a "null.ToString()" and thus an error when executing the expression if (newLeft.Type != newRight.Type && newRight.Type == typeof(string) && !IsNullConstant(newLeft)) { newLeft = Call(newLeft, typeof(object).GetDeclaredMethod("ToString")); } if (newRight.Type != newLeft.Type && newLeft.Type == typeof(string) && !IsNullConstant(newRight)) { newRight = Call(newRight, typeof(object).GetDeclaredMethod("ToString")); } CheckNullableToNonNullableChanges(node.Left, node.Right, ref newLeft, ref newRight); CheckNullableToNonNullableChanges(node.Right, node.Left, ref newRight, ref newLeft); } } } switch (node.NodeType) { case ExpressionType.Add: return(MakeBinary(node.NodeType, newLeft, newRight, node.IsLiftedToNull, node.Method)); default: return(MakeBinary(node.NodeType, newLeft, newRight)); } bool IsNullConstant(Expression expression) => expression is ConstantExpression constant && constant.Value == null; }
private Expression GetConvertedSubMemberCall(MemberExpression node) { var baseExpression = Visit(node.Expression); var propertyMap = FindPropertyMapOfExpression(node.Expression as MemberExpression); if (propertyMap == null) return node; var sourceType = propertyMap.SourceMember.GetMemberType(); var destType = propertyMap.DestinationPropertyType; if (sourceType == destType) return Expression.MakeMemberAccess(baseExpression, node.Member); var typeMap = _configurationProvider.FindTypeMapFor(sourceType, destType); var subVisitor = new MappingVisitor(_configurationProvider, typeMap, node.Expression, baseExpression, this); var newExpression = subVisitor.Visit(node); _destSubTypes = _destSubTypes.Concat(subVisitor._destSubTypes).ToArray(); return newExpression; }
public object Map(ResolutionContext context, IMappingEngineRunner mapper) { var sourceDelegateType = context.SourceType.GetGenericArguments()[0]; var destDelegateType = context.DestinationType.GetGenericArguments()[0]; var expression = (LambdaExpression)context.SourceValue; if (sourceDelegateType.GetGenericTypeDefinition() != destDelegateType.GetGenericTypeDefinition()) { throw new AutoMapperMappingException("Source and destination expressions must be of the same type."); } var parameters = expression.Parameters.ToArray(); var body = expression.Body; for (int i = 0; i < expression.Parameters.Count; i++) { var sourceParamType = sourceDelegateType.GetGenericArguments()[i]; var destParamType = destDelegateType.GetGenericArguments()[i]; if (sourceParamType == destParamType) { continue; } var typeMap = mapper.ConfigurationProvider.FindTypeMapFor(destParamType, sourceParamType); if (typeMap == null) { throw new AutoMapperMappingException( string.Format( "Could not find type map from destination type {0} to source type {1}. Use CreateMap to create a map from the source to destination types.", destParamType, sourceParamType)); } var oldParam = expression.Parameters[i]; var newParam = Expression.Parameter(typeMap.SourceType, oldParam.Name); parameters[i] = newParam; var visitor = new MappingVisitor(typeMap, oldParam, newParam); body = visitor.Visit(body); } return(Expression.Lambda(body, parameters)); }
public Expression Map(Expression expression, Type sourceType, Type targetType) { Dictionary <string, IMappingAssociation> assocs; if (!_associations.TryGetValue(new TypeMapKey(sourceType, targetType), out assocs)) { throw new InvalidOperationException(string.Format("Mapping from type {0} to type {1} is not configured", sourceType, targetType)); } var ctx = new MapContext { From = sourceType, To = targetType, Associations = assocs }; var visitor = new MappingVisitor(ctx, this); var morphed = visitor.Visit(expression); return(morphed); }
private Expression GetConvertedSubMemberCall(MemberExpression node) { var baseExpression = Visit(node.Expression); var propertyMap = FindPropertyMapOfExpression(node.Expression as MemberExpression); if (propertyMap == null) { return(node); } var sourceType = GetSourceType(propertyMap); var destType = propertyMap.DestinationType; if (sourceType == destType) { return(MakeMemberAccess(baseExpression, node.Member)); } var typeMap = _configurationProvider.Internal().ResolveTypeMap(sourceType, destType); var subVisitor = new MappingVisitor(_configurationProvider, typeMap, node.Expression, baseExpression, this); var newExpression = subVisitor.Visit(node); _destSubTypes = _destSubTypes.Concat(subVisitor._destSubTypes).ToArray(); return(newExpression); }
private Expression GetConvertedArgument(Expression node) { var baseExpression = Visit(node); if (node.Type == baseExpression.Type) { return(baseExpression); } var propertyMap = FindPropertyMapOfExpression(node as MemberExpression); if (propertyMap == null) { return(ExpressionFactory.ToType(baseExpression, node.Type)); } var sourceType = GetSourceType(propertyMap); var destType = propertyMap.DestinationPropertyType; if (sourceType != destType) { if (ReflectionHelper.CanImplicitConvert(sourceType, destType)) { return(ExpressionFactory.ToType(baseExpression, destType)); } } var typeMap = _configurationProvider.ResolveTypeMap(sourceType, destType); if (typeMap != null) { var visitor = new MappingVisitor(_configurationProvider, typeMap, baseExpression, node, this); return(visitor.Visit(node)); } return(baseExpression); }