惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
U
Unit 42
GbyAI
GbyAI
M
MIT News - Artificial intelligence
美团技术团队
罗磊的独立博客
雷峰网
雷峰网
量子位
博客园 - 【当耐特】
Last Week in AI
Last Week in AI
D
Docker
小众软件
小众软件
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
阮一峰的网络日志
阮一峰的网络日志
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
WordPress大学
WordPress大学
V
V2EX
博客园_首页
腾讯CDC
The Cloudflare Blog
A
About on SuperTechFans
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

博客园 - 哑吧湖大水怪

MAF框架架构设计概览 rabbitmq 相关概念 unity 三种注入示例 DNS解析过程详解 手工设置Windows服务依赖关系 .NET Micro Framework简介 .net MF 学习 数码管显示 .NET MF固件部署 LED灯控制 Hello World 你懂的 .NET MF环境的安装 str to date C#实现在WinForm窗口标题栏上添加按钮 摄像头操作(转) 线程间操作控件 获取客户端相关信息 任务栏的显示与隐藏 winfrom 特效 [转载]
使用AutoMapper时Expression的转换
哑吧湖大水怪 · 2016-01-18 · via 博客园 - 哑吧湖大水怪

此文章为转载: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