• 使用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
  • 相关阅读:
    怎样使用 Apache ab 以及 OneAPM 进行压力測试?
    opencv之haar特征+AdaBoos分类器算法流程(三)
    分区函数Partition By的与row_number()的用法以及与排序rank()的用法详解(获取分组(分区)中前几条记录)
    REST API 调用 方法
    WebApi的安全性及其解决方案
    使用Topshelf创建Windows服务
    LINQ查询操作符之First、FirstOrDefault、Last、LastOrDefault、ElementAt、ElementAtOrDefault、Contains、Any、All、Count
    sqlbulkcopy 多表批量保存
    C#使用HttpWebRequest和HttpWebResponse上传文件示例
    C#模拟客户端发送数据示例
  • 原文地址:https://www.cnblogs.com/lscy/p/5138766.html
Copyright © 2020-2023  润新知