使用AutoMapper时Expression的转换

此文章为转载:http://www.bubuko.com/infodetail-699735.html

参考链接:

http://q.cnblogs.com/q/34480/   dudu有回复,其中一个链接http://stackoverflow.com/questions/7424501/automapper-for-funcs-between-selector-types可以打开,并且本人主要参考此链接进行修改

下文链接为automapper相关源码

http://www.symbolsource.org/Public/Metadata/NuGet/Project/AutoMapper/3.3.0-ci1017/Release/Unsupported,Version%3Dv0.0/AutoMapper/AutoMapper/Internal/MappingExpression.cs?ImageName=AutoMapper

 

以下为转载内容:

 

问题描述

项目中使用AutoMapper进行VO&DTO&Entity的互相映射,但是默认Map方法不支持Expression的转换。如

Expression<Func<Entity,bool>> fun = _ => _.A == "A";

希望转换成

Expression<Func<Dto,bool>> fun = _ => _.A == "A";

 

似乎解决方案就是解析ExpressionTree并映射替换节点。正好找到了人家的提问和解决方案

http://stackoverflow.com/questions/7424501/automapper-for-funcs-between-selector-types

 

改造一下支持泛型,代码如下:

 1 #region using namespace
 2 
 3 using System;
 4 using System.Collections.Concurrent;
 5 using System.Linq.Expressions;
 6 using System.Reflection;
 7 using AutoMapper;
 8 using AutoMapper.QueryableExtensions;
 9 
10 #endregion
11 
12 namespace Core
13 {
14     public static class FunctionCompositionExtensions
15     {
16         private static readonly ConcurrentDictionary<Tuple<Type, Type>, Tuple<MethodInfo, Expression>> Dictionary =
17             new ConcurrentDictionary<Tuple<Type, Type>, Tuple<MethodInfo, Expression>>();
18 
19         private static readonly MethodInfo Method = typeof (FunctionCompositionExtensions).GetMethod("Compose",
20             BindingFlags.NonPublic | BindingFlags.Static);
21 
22         public static Expression<Func<TDestination, bool>> MapExpression<TSource, TDestination>(
23             this Expression<Func<TSource, bool>> selector)
24         {
25             var bulidMethod = Dictionary.GetOrAdd(new Tuple<Type, Type>(typeof (TSource), typeof (TDestination)), _ =>
26             {
27                 var expression = Mapper.Engine.CreateMapExpression<TDestination, TSource>();
28                 return new Tuple<MethodInfo, Expression>(
29                     Method.MakeGenericMethod(typeof (TDestination), typeof (bool), typeof (TSource)), expression);
30             });
31             return
32                 bulidMethod.Item1.Invoke(null, new object[] {selector, bulidMethod.Item2}) as
33                     Expression<Func<TDestination, bool>>;
34         }
35 
36         public static Expression<Func<TX, TY>> Compose<TX, TY, TZ>(this Expression<Func<TZ, TY>> outer,
37             Expression<Func<TX, TZ>> inner)
38         {
39             return Expression.Lambda<Func<TX, TY>>(
40                 ParameterReplacer.Replace(outer.Body, outer.Parameters[0], inner.Body),
41                 inner.Parameters[0]);
42         }
43 
44         public static Expression<Predicate<TX>> ComposePredicate<TX, TZ>(this Expression<Predicate<TZ>> outer,
45             Expression<Func<TX, TZ>> inner)
46         {
47             return Expression.Lambda<Predicate<TX>>(
48                 ParameterReplacer.Replace(outer.Body, outer.Parameters[0], inner.Body),
49                 inner.Parameters[0]);
50         }
51     }
52 
53     class ParameterReplacer : ExpressionVisitor
54     {
55         private readonly ParameterExpression _parameter;
56         private readonly Expression _replacement;
57 
58         private ParameterReplacer(ParameterExpression parameter, Expression replacement)
59         {
60             _parameter = parameter;
61             _replacement = replacement;
62         }
63 
64         public static Expression Replace(Expression expression, ParameterExpression parameter, Expression replacement)
65         {
66             return new ParameterReplacer(parameter, replacement).Visit(expression);
67         }
68 
69         protected override Expression VisitParameter(ParameterExpression parameter)
70         {
71             if (parameter == _parameter)
72             {
73                 return _replacement;
74             }
75             return base.VisitParameter(parameter);
76         }
77     }
78 }
View Code

 

测试

 1 public class Entity
 2 {
 3 public string A { get; set; }
 4 }
 5 
 6 public class Dto
 7 {
 8 public string A { get; set; }
 9 }
10 
11 
12 Mapper.CreateMap<Entity, Dto>();
13 Mapper.CreateMap<Dto, Entity>();
14 
15 
16 var list = new List<Dto>()
17 {
18 new Dto() {A = "A"},
19 new Dto() {A = "B"},
20 new Dto() {A = "C"},
21 new Dto() {A = "D"},
22 new Dto() {A = "E"},
23 };
24 
25 //Predicate<Entity> fun = _ => _.A =="A";
26 Expression<Func<Entity,bool>> funEntity = _ => _.A == "A";
27 
28 var query = list.Where(funEntity.MapExpression<Entity, Dto>().Compile());
29 Assert.True(query.Count() == 1);
30 
31 Expression<Func<Entity, bool>> funEntity2 = _ => _.A == "F";
32 var query2 = list.Where(funEntity2.MapExpression<Entity, Dto>().Compile());
33 Assert.True(query2.Count() == 0);
View Code

 

你可能感兴趣的:(使用AutoMapper时Expression的转换)