问题描述

项目中使用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

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

 public static class FunctionCompositionExtensions
{
private static ConcurrentDictionary<Tuple<Type, Type>, Tuple<MethodInfo, Expression>> dictionary = new ConcurrentDictionary<Tuple<Type, Type>, Tuple<MethodInfo, Expression>>();
private static MethodInfo method = typeof(FunctionCompositionExtensions).GetMethod("Compose", BindingFlags.NonPublic | BindingFlags.Static); public static Expression<Func<D, bool>> MapExpression<S, D>(this Expression<Func<S, bool>> selector)
{
var bulidMethod = dictionary.GetOrAdd(new Tuple<Type, Type>(typeof(S), typeof(D)), _ =>
{
var expression = Mapper.Engine.CreateMapExpression<D, S>();
return new Tuple<MethodInfo, Expression>(method.MakeGenericMethod(typeof(D), typeof(bool), typeof(S)), expression);
});
return bulidMethod.Item1.Invoke(null, new[] { selector, bulidMethod.Item2 }) as Expression<Func<D, bool>>; } static Expression<Func<X, Y>> Compose<X, Y, Z>(this Expression<Func<Z, Y>> outer, Expression<Func<X, Z>> inner)
{
return Expression.Lambda<Func<X, Y>>(
ParameterReplacer.Replace(outer.Body, outer.Parameters[0], inner.Body),
inner.Parameters[0]);
} static Expression<Predicate<X>> ComposePredicate<X, Z>(this Expression<Predicate<Z>> outer, Expression<Func<X, Z>> inner)
{
return Expression.Lambda<Predicate<X>>(
ParameterReplacer.Replace(outer.Body, outer.Parameters[0], inner.Body),
inner.Parameters[0]);
}
} class ParameterReplacer : ExpressionVisitor
{
private ParameterExpression _parameter;
private Expression _replacement; private ParameterReplacer(ParameterExpression parameter, Expression replacement)
{
_parameter = parameter;
_replacement = replacement;
} public static Expression Replace(Expression expression, ParameterExpression parameter, Expression replacement)
{
return new ParameterReplacer(parameter, replacement).Visit(expression);
} protected override Expression VisitParameter(ParameterExpression parameter)
{
if (parameter == _parameter)
{
return _replacement;
}
return base.VisitParameter(parameter);
}
}

测试

public class Entity
{
public string A { get; set; }
} public class Dto
{
public string A { get; set; }
} Mapper.CreateMap<Entity, Dto>();
Mapper.CreateMap<Dto, Entity>(); var list = new List<Dto>()
{
new Dto() {A = "A"},
new Dto() {A = "B"},
new Dto() {A = "C"},
new Dto() {A = "D"},
new Dto() {A = "E"},
}; //Predicate<Entity> fun = _ => _.A =="A";
Expression<Func<Entity,bool>> funEntity = _ => _.A == "A"; var query = list.Where(funEntity.MapExpression<Entity, Dto>().Compile());
Assert.True(query.Count() == 1); Expression<Func<Entity, bool>> funEntity2 = _ => _.A == "F";
var query2 = list.Where(funEntity2.MapExpression<Entity, Dto>().Compile());
Assert.True(query2.Count() == 0);

AutoMapper映射ExpressionTree的更多相关文章

  1. 配置AutoMapper映射规则《转》

    配置AutoMapper映射规则 AutoMapper是基于约定的,因此在实用映射之前,我们需要先进行映射规则的配置. public class Source { public int SomeVal ...

  2. ASP.NET Core搭建多层网站架构【8.2-使用AutoMapper映射实体对象】

    2020/01/29, ASP.NET Core 3.1, VS2019, AutoMapper.Extensions.Microsoft.DependencyInjection 7.0.0 摘要:基 ...

  3. 使用 AutoMapper 映射 IDataReader、DataSet、DataTable 到实体类

    AutoMapper是一个.NET的对象映射工具. 项目地址:https://github.com/AutoMapper/AutoMapper. 帮助文档:https://github.com/Aut ...

  4. 一文为你详细讲解对象映射库【AutoMapper】所支持场景

    前言 在AutoMapper未出世前,对象与对象之间的映射,我们只能通过手动为每个属性一一赋值,时间长了不仅是我们而且老外也觉得映射代码很无聊啊.这个时候老外的所写的强大映射库AutoMapper横空 ...

  5. .NET CORE 中使用AutoMapper进行对象映射

    简介 AutoMapper uses a fluent configuration API to define an object-object mapping strategy. AutoMappe ...

  6. NetCore+AutoMapper多个对象映射到一个Dto对象

    目录 一. 定义源映射类和被映射类DTO二.注入AutoMapper三.配置映射四.写测试 一.定义源映射对象 为了体现AutoMapper映射特性,在SocialAttribute中的Name属性没 ...

  7. 在 ASP.NET Core 项目中使用 AutoMapper 进行实体映射

    一.前言 在实际项目开发过程中,我们使用到的各种 ORM 组件都可以很便捷的将我们获取到的数据绑定到对应的 List<T> 集合中,因为我们最终想要在页面上展示的数据与数据库实体类之间可能 ...

  8. ASP.NET Core Web 应用程序系列(五)- 在ASP.NET Core中使用AutoMapper进行实体映射

    本章主要简单介绍下在ASP.NET Core中如何使用AutoMapper进行实体映射.在正式进入主题之前我们来看下几个概念: 1.数据库持久化对象PO(Persistent Object):顾名思义 ...

  9. ASP.NET CORE 中使用AutoMapper进行对象映射

    ASP.NET CORE 中使用AutoMapper进行对象映射 1.什么是AutoMapper? AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DT ...

随机推荐

  1. 基于soapUI构建WebService测试框架

    基于soapUI构建WebService测试框架 http://www.docin.com/p-775523285.html

  2. 高效的INSERT INTO SELECT和SELECT INTO

    1.INSERT INTO SELECT,目标表必须存在,才可批量插入 INSERT INTO 目标表Table(field1,field2,field2,...) SELECT value1,val ...

  3. tomcat的网站屏蔽IP的方法

    <Host> <Valve className="org.apache.catalina.valves.RemoteAddrValve"  deny=" ...

  4. 实时流式计算框架Storm 0.9.0发布通知(中文版)

    Storm0.9.0发布通知中文翻译版(2013/12/10 by 富士通邵贤军 有错误一定告诉我 shaoxianjun@hotmail.com^_^) 我们很高兴宣布Storm 0.9.0已经成功 ...

  5. linux 下面 jdk1.7 rpm 包的安装

    1.下载安装jdk7.0 for linux 我下载的版本为:jdk-7u2-linux-i586.rpm 下载地址为:http://www.oracle.com/technetwork/java/j ...

  6. 尝试在virtualbox fedora21 下安装additions和mount share folder

    安装这个additions的过程,基本上可以参照 http://gamblisfx.com/how-to-install-virtualbox-guest-additions-on-fedora-21 ...

  7. Flex Error #2156问题

    出现这个问题是因为应用程序使用了特殊端口,修改端口就可以解决. 特殊端口列表 A security change has been made in Adobe Flash Player 9.0.115 ...

  8. (转)ubuntu安装opengl

    $ sudo apt-get install build-essential 安装OpenGL Library接下来要把我们会用到的 Library 装上去,首先安装 OpenGL Library $ ...

  9. [OpenCV] HighGUI

    From: http://www.cnblogs.com/xylc/p/3406026.html 本模块为跨平台的gui/IO组件,支持平台包括windows,linux,mac,IOS,androi ...

  10. iOS-文字自适应

    1.自动改变Label的宽和高 - (void)createLabel1 { UILabel * label = [[UILabel alloc] initWithFrame:CGRectZero]; ...