public static Expression<Func<TFrom, TTo>> AndLambdas<TFrom, TTo>(this Expression<Func<TFrom, TTo>> first, Expression<Func<TFrom, TTo>> second) { ParameterExpression paramToUse = first.Parameters[0]; Expression bodyLeft = first.Body; ConversionVisitor visitor = new ConversionVisitor(paramToUse, second.Parameters[0]); Expression bodyRight = visitor.Visit(second.Body); return Expression.Lambda<Func<TFrom, TTo>>(Expression.MakeBinary(ExpressionType.AndAlso, bodyLeft, bodyRight), first.Parameters); }
public static Expression <Func <TTo, TR> > Convert <TFrom, TR>( Expression <Func <TFrom, TR> > e ) { var oldParameter = e.Parameters[0]; var newParameter = Expression.Parameter(typeof(TTo), oldParameter.Name); var converter = new ConversionVisitor(newParameter, oldParameter); var newBody = converter.Visit(e.Body); return(Expression.Lambda <Func <TTo, TR> >(newBody, newParameter)); }
public static Expression <Func <TTo, TR> > Convert <TFrom, TR>(Expression <Func <TFrom, TR> > e) { if (e == null) { throw new ArgumentNullException(nameof(e)); } var oldParameter = e.Parameters[0]; var newParameter = Expression.Parameter(typeof(TTo), oldParameter.Name); var converter = new ConversionVisitor(newParameter, oldParameter); var newBody = converter.Visit(e.Body); return(Expression.Lambda <Func <TTo, TR> >(newBody, newParameter)); }
/// <summary> /// Convert expression from type [TFrom] to type [TTo] /// </summary> /// <typeparam name="TFrom"></typeparam> /// <typeparam name="TTo"></typeparam> /// <typeparam name="TReturn"></typeparam> /// <param name="e"></param> /// <returns></returns> public static Expression <Func <TTo, TResult> > Convert <TFrom, TTo, TResult>(Expression <Func <TFrom, TResult> > e) { if (e == null) { return(null); } var oldParameter = e.Parameters[0]; var newParameter = Expression.Parameter(typeof(TTo), oldParameter.Name); var converter = new ConversionVisitor(newParameter, oldParameter); try { var newBody = converter.Visit(e.Body); return(Expression.Lambda <Func <TTo, TResult> >(newBody, newParameter)); } catch (ArgumentException) { return(null); } }
public ExpressionResolutionResult ResolveExpression(Type currentType, Expression instanceParameter) { Expression currentChild = instanceParameter; Type currentChildType = currentType; foreach (var resolver in GetSourceValueResolvers()) { var getter = resolver as IMemberGetter; if (getter != null) { var memberInfo = getter.MemberInfo; var propertyInfo = memberInfo as PropertyInfo; if (propertyInfo != null) { currentChild = Expression.Property(currentChild, propertyInfo); currentChildType = propertyInfo.PropertyType; } else { throw new NotImplementedException("Expressions mapping from methods not supported yet."); } } else { var oldParameter = CustomExpression.Parameters.Single(); var newParameter = instanceParameter; var converter = new ConversionVisitor(newParameter, oldParameter); currentChild = converter.Visit(CustomExpression.Body); currentChildType = currentChild.Type; } } return(new ExpressionResolutionResult(currentChild, currentChildType)); }
private static ExpressionResolutionResult ResolveExpression(PropertyMap propertyMap, Type currentType, Expression instanceParameter) { Expression currentChild = instanceParameter; Type currentChildType = currentType; foreach (var resolver in propertyMap.GetSourceValueResolvers()) { var getter = resolver as IMemberGetter; if (getter != null) { var memberInfo = getter.MemberInfo; var propertyInfo = memberInfo as PropertyInfo; if (propertyInfo != null) { currentChild = Expression.Property(currentChild, propertyInfo); currentChildType = propertyInfo.PropertyType; } else { currentChildType = currentChild.Type; } } else { var oldParameter = propertyMap.CustomExpression.Parameters.Single(); var newParameter = instanceParameter; var converter = new ConversionVisitor(newParameter, oldParameter); currentChild = converter.Visit(propertyMap.CustomExpression.Body); currentChildType = currentChild.Type; } } return(new ExpressionResolutionResult(currentChild, currentChildType)); }
private LambdaExpression CreateMapExpression( Type typeIn, Type typeOut) { var typeMap = ConfigurationProvider.FindTypeMapFor(typeIn, typeOut); // this is the input parameter of this expression with name <variableName> ParameterExpression instanceParameter = Expression.Parameter(typeIn); var bindings = new List <MemberBinding>(); foreach (var propertyMap in typeMap.GetPropertyMaps().Where(pm => pm.CanResolveValue())) { var destinationProperty = propertyMap.DestinationProperty; var destinationMember = destinationProperty.MemberInfo; Expression currentChild = instanceParameter; Type currentChildType = typeIn; foreach (var resolver in propertyMap.GetSourceValueResolvers()) { var getter = resolver as IMemberGetter; if (getter != null) { var memberInfo = getter.MemberInfo; var propertyInfo = memberInfo as PropertyInfo; if (propertyInfo != null) { currentChild = Expression.Property(currentChild, propertyInfo); currentChildType = propertyInfo.PropertyType; } } else { var oldParameter = ((LambdaExpression)propertyMap.CustomExpression).Parameters.Single(); var newParameter = instanceParameter; var converter = new ConversionVisitor(newParameter, oldParameter); currentChild = converter.Visit(((LambdaExpression)propertyMap.CustomExpression).Body); var propertyInfo = propertyMap.SourceMember as PropertyInfo; if (propertyInfo != null) { currentChildType = propertyInfo.PropertyType; } } } var prop = destinationProperty.MemberInfo as PropertyInfo; // next to lists, also arrays // and objects!!! if (prop != null && prop.PropertyType.GetInterface("IEnumerable", true) != null && prop.PropertyType != typeof(string)) { Type destinationListType = prop.PropertyType.GetGenericArguments().First(); Type sourceListType = null; // is list sourceListType = currentChildType.GetGenericArguments().First(); //var newVariableName = "t" + (i++); var transformedExpression = CreateMapExpression(sourceListType, destinationListType); MethodCallExpression selectExpression = Expression.Call( typeof(Enumerable), "Select", new[] { sourceListType, destinationListType }, currentChild, transformedExpression); if (typeof(IList).IsAssignableFrom(prop.PropertyType)) { MethodCallExpression toListCallExpression = Expression.Call( typeof(Enumerable), "ToList", new Type[] { destinationListType }, selectExpression); // todo .ToArray() bindings.Add(Expression.Bind(destinationMember, toListCallExpression)); } else { // destination type implements ienumerable, but is not an ilist. allow deferred enumeration bindings.Add(Expression.Bind(destinationMember, selectExpression)); } } else { // does of course not work for subclasses etc./generic ... if (currentChildType != prop.PropertyType && // avoid nullable etc. prop.PropertyType.BaseType != typeof(ValueType) && prop.PropertyType.BaseType != typeof(Enum)) { var transformedExpression = CreateMapExpression(currentChildType, prop.PropertyType); var expr2 = Expression.Invoke( transformedExpression, currentChild ); bindings.Add(Expression.Bind(destinationMember, expr2)); } else { bindings.Add(Expression.Bind(destinationMember, currentChild)); } } } var total = Expression.MemberInit( Expression.New(typeOut), bindings.ToArray() ); return(Expression.Lambda(total, instanceParameter)); }
void InsertComments(CompilerCompilationUnit top, ConversionVisitor conversionVisitor) { AstNode insertionPoint = conversionVisitor.Unit.FirstChild; foreach (var special in top.SpecialsBag.Specials) { AstNode newLeaf = null; Role role = null; bool isDocumentationComment = false; var comment = special as SpecialsBag.Comment; if (comment != null) { // HACK: multiline documentation comment detection; better move this logic into the mcs tokenizer bool isMultilineDocumentationComment = (comment.CommentType == SpecialsBag.CommentType.Multi && comment.Content.StartsWith("*", StringComparison.Ordinal) && !comment.Content.StartsWith("**", StringComparison.Ordinal)); isDocumentationComment = comment.CommentType == SpecialsBag.CommentType.Documentation || isMultilineDocumentationComment; if (conversionVisitor.convertTypeSystemMode && !isDocumentationComment) continue; var type = isMultilineDocumentationComment ? CommentType.MultiLineDocumentation : (CommentType)comment.CommentType; var start = new TextLocation(comment.Line, comment.Col); var end = new TextLocation(comment.EndLine, comment.EndCol); newLeaf = new Comment(type, start, end) { StartsLine = comment.StartsLine, Content = isMultilineDocumentationComment ? comment.Content.Substring(1) : comment.Content }; role = Roles.Comment; } else if (!GenerateTypeSystemMode) { var pragmaDirective = special as SpecialsBag.PragmaPreProcessorDirective; if (pragmaDirective != null) { var pragma = new PragmaWarningPreprocessorDirective(new TextLocation(pragmaDirective.Line, pragmaDirective.Col), new TextLocation(pragmaDirective.EndLine, pragmaDirective.EndCol)); pragma.AddChild(new CSharpTokenNode(new TextLocation(pragmaDirective.Line, pragmaDirective.Col), PragmaWarningPreprocessorDirective.PragmaKeywordRole), PragmaWarningPreprocessorDirective.PragmaKeywordRole); pragma.AddChild(new CSharpTokenNode(new TextLocation(pragmaDirective.Line, pragmaDirective.WarningColumn), PragmaWarningPreprocessorDirective.WarningKeywordRole), PragmaWarningPreprocessorDirective.WarningKeywordRole); var pragmaRole = pragmaDirective.Disalbe ? PragmaWarningPreprocessorDirective.DisableKeywordRole : PragmaWarningPreprocessorDirective.RestoreKeywordRole; pragma.AddChild(new CSharpTokenNode(new TextLocation(pragmaDirective.Line, pragmaDirective.DisableRestoreColumn), pragmaRole), pragmaRole); foreach (var code in pragmaDirective.Codes) { pragma.AddChild((PrimitiveExpression)conversionVisitor.Visit(code), PragmaWarningPreprocessorDirective.WarningRole); } newLeaf = pragma; role = Roles.PreProcessorDirective; goto end; } var lineDirective = special as SpecialsBag.LineProcessorDirective; if (lineDirective != null) { var pragma = new LinePreprocessorDirective(new TextLocation(lineDirective.Line, lineDirective.Col), new TextLocation(lineDirective.EndLine, lineDirective.EndCol)); pragma.LineNumber = lineDirective.LineNumber; pragma.FileName = lineDirective.FileName; newLeaf = pragma; role = Roles.PreProcessorDirective; goto end; } var directive = special as SpecialsBag.PreProcessorDirective; if (directive != null) { newLeaf = new PreProcessorDirective((PreProcessorDirectiveType)((int)directive.Cmd & 0xF), new TextLocation(directive.Line, directive.Col), new TextLocation(directive.EndLine, directive.EndCol)) { Argument = directive.Arg, Take = directive.Take }; role = Roles.PreProcessorDirective; } end: ; } if (newLeaf != null) { InsertComment(ref insertionPoint, newLeaf, role, isDocumentationComment, conversionVisitor.Unit); } } if (!GenerateTypeSystemMode) { // We cannot insert newlines in the same loop as comments/preprocessor directives // because they are not correctly ordered in the specials bag insertionPoint = conversionVisitor.Unit.FirstChild; for (int i = 0; i < top.SpecialsBag.Specials.Count; i++) { var newLine = top.SpecialsBag.Specials [i] as SpecialsBag.NewLineToken; if (newLine != null) { var newLeaf = new NewLineNode(new TextLocation(newLine.Line, newLine.Col + 1)); newLeaf.NewLineType = newLine.NewLine == SpecialsBag.NewLine.Unix ? UnicodeNewline.LF : UnicodeNewline.CRLF; InsertComment(ref insertionPoint, newLeaf, Roles.NewLine, false, conversionVisitor.Unit); } } } }
private LambdaExpression CreateMapExpression( Type typeIn, Type typeOut) { var typeMap = ConfigurationProvider.FindTypeMapFor(typeIn, typeOut); if (typeMap == null) { throw new ArgumentException(string.Format("Type map for converting from \"{0}\" to \"{1}\" was not found. Please use Mapper.CreateMap<{0}, {1}>() to register a type map.", typeIn.Name, typeOut.Name)); } // this is the input parameter of this expression with name <variableName> ParameterExpression instanceParameter = Expression.Parameter(typeIn); var bindings = new List <MemberBinding>(); foreach (var propertyMap in typeMap.GetPropertyMaps().Where(pm => pm.CanResolveValue())) { var destinationProperty = propertyMap.DestinationProperty; var destinationMember = destinationProperty.MemberInfo; Expression currentChild = instanceParameter; Type currentChildType = typeIn; foreach (var resolver in propertyMap.GetSourceValueResolvers()) { var getter = resolver as IMemberGetter; if (getter != null) { var memberInfo = getter.MemberInfo; var propertyInfo = memberInfo as PropertyInfo; if (propertyInfo != null) { currentChild = Expression.Property(currentChild, propertyInfo); currentChildType = propertyInfo.PropertyType; } } else { var oldParameter = propertyMap.CustomExpression.Parameters.Single(); var newParameter = instanceParameter; var converter = new ConversionVisitor(newParameter, oldParameter); currentChild = converter.Visit(propertyMap.CustomExpression.Body); var propertyInfo = propertyMap.SourceMember as PropertyInfo; if (propertyInfo != null) { currentChildType = propertyInfo.PropertyType; } else { currentChildType = currentChild.Type; } } } var prop = destinationProperty.MemberInfo as PropertyInfo; // next to lists, also arrays // and objects!!! if (prop != null && prop.PropertyType.GetInterface("IEnumerable", true) != null && prop.PropertyType != typeof(string)) { Type destinationListType = prop.PropertyType.GetGenericArguments().FirstOrDefault() ?? prop.PropertyType.GetElementType();
private LambdaExpression CreateMapExpression( Type typeIn, Type typeOut) { var typeMap = ConfigurationProvider.FindTypeMapFor(typeIn, typeOut); // this is the input parameter of this expression with name <variableName> ParameterExpression instanceParameter = Expression.Parameter(typeIn); var bindings = new List <MemberBinding>(); foreach (var propertyMap in typeMap.GetPropertyMaps().Where(pm => pm.CanResolveValue())) { var destinationProperty = propertyMap.DestinationProperty; var destinationMember = destinationProperty.MemberInfo; Expression currentChild = instanceParameter; Type currentChildType = typeIn; foreach (var resolver in propertyMap.GetSourceValueResolvers()) { var getter = resolver as IMemberGetter; if (getter != null) { var memberInfo = getter.MemberInfo; var propertyInfo = memberInfo as PropertyInfo; if (propertyInfo != null) { currentChild = Expression.Property(currentChild, propertyInfo); currentChildType = propertyInfo.PropertyType; } } else { var oldParameter = ((LambdaExpression)propertyMap.CustomExpression).Parameters.Single(); var newParameter = instanceParameter; var converter = new ConversionVisitor(newParameter, oldParameter); currentChild = converter.Visit(((LambdaExpression)propertyMap.CustomExpression).Body); var propertyInfo = propertyMap.SourceMember as PropertyInfo; if (propertyInfo != null) { currentChildType = propertyInfo.PropertyType; } } } var prop = destinationProperty.MemberInfo as PropertyInfo; // next to lists, also arrays // and objects!!! if (prop != null && prop.PropertyType.GetInterface("IEnumerable", true) != null && prop.PropertyType != typeof(string)) { Type destinationListType = prop.PropertyType.GetGenericArguments().First(); Type sourceListType = null; // is list sourceListType = currentChildType.GetGenericArguments().First(); //var newVariableName = "t" + (i++); var transformedExpression = CreateMapExpression(sourceListType, destinationListType); MethodCallExpression selectExpression = Expression.Call( typeof(Enumerable), "Select", new[] { sourceListType, destinationListType }, currentChild, transformedExpression); if (typeof(IList).IsAssignableFrom(prop.PropertyType)) { MethodCallExpression toListCallExpression = Expression.Call( typeof(Enumerable), "ToList", new Type[] { destinationListType }, selectExpression); // todo .ToArray() bindings.Add(Expression.Bind(destinationMember, toListCallExpression)); } else { // destination type implements ienumerable, but is not an ilist. allow deferred enumeration bindings.Add(Expression.Bind(destinationMember, selectExpression)); } } else { // does of course not work for subclasses etc./generic ... if (currentChildType != prop.PropertyType && // avoid nullable etc. prop.PropertyType.BaseType != typeof(ValueType) && prop.PropertyType.BaseType != typeof(Enum)) { var transformedExpression = CreateMapExpression(currentChildType, prop.PropertyType); var expr2 = Expression.Invoke( transformedExpression, currentChild ); bindings.Add(Expression.Bind(destinationMember, expr2)); } else { bindings.Add(Expression.Bind(destinationMember, currentChild)); } } } Expression total; if (typeOut.IsAbstract) { if (typeMap.CustomMapper == null) { throw new AutoMapperMappingException( String.Format("Abstract type {0} can not be mapped without custom mapper (tip: use ConvertUsing)", typeOut.Name)); } // We are going to return roughly following expression // typeOut (typeIn)x => (typeOut)(typeMap.CustomMapper.Invoke(new ResolutionContext(typeMap, x, typeIn, typeOut, options))) // This expression generates a new ResolutionContext // for the custom mapper (ResolveCore) var context = Expression.MemberInit( Expression.New( typeof(ResolutionContext).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(TypeMap), typeof(object), typeof(Type), typeof(Type), typeof(MappingOperationOptions) }, null), new List <Expression> { Expression.Constant(typeMap), instanceParameter, // Using the original parameter Expression.Constant(typeIn), Expression.Constant(typeOut), Expression.Constant(new MappingOperationOptions()) }) ); // This expression gets the CustomMapper from the typeMap Expression <Func <TypeMap, Func <ResolutionContext, object> > > method = x => x.CustomMapper; var customMapper = Expression.Invoke(method, Expression.Constant(typeMap)); // This expression calls the Invoke method from the CustomMapper func var invoke = Expression.Call(customMapper, typeof(Func <ResolutionContext, object>).GetMethod("Invoke"), context); // We have to convert the object from Invoke to typeOut total = Expression.Convert(invoke, typeOut); } else { total = Expression.MemberInit( Expression.New(typeOut), bindings.ToArray() ); } return(Expression.Lambda(total, instanceParameter)); }