在实体与DTO之间,我们一般都需要进行映射。如果手动的来进行转换,实在是太麻烦。所以就产生了很多映射工具,比如AutoMapper,EmitMapper。而经过一些对比,EmitMapper比较快,接近于手工转换的速度。

          EmitMapper使用非常简单,对于那种属性名一样的,直接使用默认映射即可。如:

ObjectsMapper<From,To> mapper = ObjectMapperManager.DefaultInstance.GetMapper<From,To>();

to = mapper.Map(from);

        它就会自动的把From对象的值赋给To对象;

       对于有一定规则的,可以使用一些扩展的方法,如:

      通过使用ConvertUsing可以配置一些组合映射.比如这个字段可以是某两个字段拼接,或者其他一些计算.具体可以参见一些使用例子:

       http://www.cnblogs.com/aaa6818162/archive/2012/06/21/2557879.html

      http://www.cnblogs.com/wuhong/archive/2011/09/21/2184313.html

          但是在使用的过程中,发现了一个问题,就是本身默认是如果属性名相同就直接映射,而使用ConvertUsing是可以自定义映射条件的.但是如果使用了ConvertUsing,那么你必需为里面每个字段都指定映射的条件.而其实真正想用的是,在实体与DTO之间,其实大部分字段的属性名称是相同的,对于这些字段,我们是想直接默认映射,而对于其他一些需要自定义映射的字段,来自定义映射规则.但实际上却达不到这种效果,一般人也不想去把每个字段的映射规则配置一下,如果这样,还不如手动写呢.

          后来在网上找到了一个例子,可以使用FlatteringConfig这个自定义配置,这个类在EmitMapper的源码中是有的,但是不是在当前的解决方案下,而是在一个叫EMConfigurations的项目里.可以这样使用这个自定义配置.

public class User

{

  public Guid Id { get; set; }

  public Company Company { get; set; }

}    

 

public class Company

{

  public Guid Id { get; set; }

}

 

public class UserDTO

{

  public Guid Id { get; set; }

  public Guid CompanyId{ get; set; }

}

ObjectMapperManager.DefaultInstance.GetMapper<User, UserDTO>(

                new FlatteringConfig()

            );

var dto = mapper.Map(new User());

          这样,它就会自动的给DTO中的CompanyId赋值,也会给Id赋值.不过有一个规则就是CompanyId的命名要有一定的规则,一定要是那个实体的名称再加上这个实体里面属性的名称.这样才能进行自动的映射.(不过这时,如果那个实体为null,那也有可能会报错,没有试过,后面有时间试一下).

          在运行的过程中,发现了FlatteringConfig类的一个bug;这个类的原始代码如下:

public class FlatteringConfig : DefaultMapConfig 

    {

        protected Func<string, string, bool> nestedMembersMatcher;

 

        public FlatteringConfig()

        {

            nestedMembersMatcher = (m1, m2) => m1.StartsWith(m2);

        }

 

        public override IMappingOperation[] GetMappingOperations(Type from, Type to)

        {

            var destinationMembers = GetDestinationMemebers(to);

            var sourceMembers = GetSourceMemebers(from);

            var result = new List<IMappingOperation>();

            foreach (var dest in destinationMembers)

            {

                var matchedChain = GetMatchedChain(dest.Name, sourceMembers).ToArray();

                if (matchedChain == null || matchedChain.Length == 0)

                {

                    continue;

                }

                result.Add(

                    new ReadWriteSimple

                    {

                        Source = new MemberDescriptor(matchedChain),

                        Destination = new MemberDescriptor(new[] { dest })

                    }

                );

            }

            return result.ToArray();

        }

 

        public DefaultMapConfig MatchNestedMembers(Func<string, string, bool> nestedMembersMatcher)

        {

            this.nestedMembersMatcher = nestedMembersMatcher;

            return this;

        }

 

        private List<MemberInfo> GetMatchedChain(string destName, List<MemberInfo> sourceMembers)

        {

            var matches = sourceMembers.Where(s => MatchMembers(destName, s.Name) || nestedMembersMatcher(destName, s.Name));

            int len = 0;

            MemberInfo match = null;

            foreach (var m in matches)

            {

                if (m.Name.Length > len)

                {

                    len = m.Name.Length;

                    match = m;

                }

            }

            if (match == null)

            {

                return null;

            }

            var result = new List<MemberInfo> { match };

            if (!MatchMembers(destName, match.Name))

            {

                result.AddRange(

                    GetMatchedChain(destName.Substring(match.Name.Length), GetDestinationMemebers(match))

                );

            }

            return result;

        }

 

        private static List<MemberInfo> GetSourceMemebers(Type t)

        {

            return GetMemebers(t)

                .Where(

                    m => 

                        m.MemberType == MemberTypes.Field || 

                        m.MemberType == MemberTypes.Property ||

                        m.MemberType == MemberTypes.Method

                )

                .ToList();

        }

 

        private static List<MemberInfo> GetDestinationMemebers(MemberInfo mi)

        {

            Type t;

            if (mi.MemberType == MemberTypes.Field)

            {

                t = mi.DeclaringType.GetField(mi.Name).FieldType;

            }

            else

            {

                t = mi.DeclaringType.GetProperty(mi.Name).PropertyType;

            }

            return GetDestinationMemebers(t);

        }

 

        private static List<MemberInfo> GetDestinationMemebers(Type t)

        {

            return GetMemebers(t).Where(m => m.MemberType == MemberTypes.Field || m.MemberType == MemberTypes.Property).ToList();

        }

 

        private static List<MemberInfo> GetMemebers(Type t)

        {

            BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;

            return t.GetMembers(bindingFlags).ToList();

        }

    }

      在GetMappingOperations方法中,修改了以下代码:(原代码中是一个判断在一起,改成分作两个判断)

var matchedChainSingle = GetMatchedChain(dest.Name, sourceMembers);

               if (matchedChainSingle == null)

               {

                   continue;

               }

               var matchedChain = matchedChainSingle.ToArray();

               if (matchedChain.Length == 0)

               {

                   continue;

               }

 

      参考资料:

      http://emitmapper.codeplex.com/

      http://stackoverflow.com/questions/9619265/emit-mapper-flattering-and-property-name-mismatch

      http://emitmapper.codeplex.com/SourceControl/changeset/view/69894#1192663

      http://emitmapper.codeplex.com/SourceControl/changeset/view/42128#691132

     http://stackoverflow.com/questions/12542749/emitmapper-flattering-config-nullreferenceexception?rq=1

EmitMapper自动映射工具的更多相关文章

  1. AutoMapper 自动映射工具

    先引用对应的DLL. 11.转换匿名对象 结合LINQ映射新的实体类. using System;using System.Collections.Generic;using System.Linq; ...

  2. 使用SpringDataJdbc的@Query注解实现自动映射结果集 ----- RowMapper接口

    使用@Query注解的时候,常常需要写sql来映射非域类的实例,通常的做法就是 实现 RowMapper接口,然后new实例一个一个的设置值进去...为此.出世了自动映射工具类 注意事项:此抽象类只是 ...

  3. [转]p2p端口映射工具 dog-tunnel

    [转]p2p端口映射工具 dog-tunnel http://www.oschina.net/p/dog-tunnel 狗洞是一个高速的 P2P 端口映射工具,同时支持Socks5代理. 0.5版后开 ...

  4. 代码自动生成工具MyGeneration之一(程序员必备工具)

    代码自动生成工具MyGeneration之一(程序员必备工具) 转 分类: C#2008-08-06 18:12 16064人阅读 评论(12) 收藏 举报 工具数据库相关数据库stringbrows ...

  5. .NET的DTO映射工具AutoMapper

    .NET的DTO映射工具AutoMapper 原文:https://github.com/AutoMapper/AutoMapper/wiki/Getting-started 参考:http://ww ...

  6. 反射+自定义注解---实现Excel数据列属性和JavaBean属性的自动映射

    简单粗暴,直奔主题.   需求:通过自定义注解和反射技术,将Excel文件中的数据自动映射到pojo类中,最终返回一个List<pojo>集合? 今天我只是通过一位使用者的身份来给各位分享 ...

  7. Touch 方法&属性 映射工具

    Touch 方法&属性 映射工具(0.5 版本) 标签 : github 线上后门与接口调试: 原先需要测试一个接口(如Dubbo.DAO), 或为线上留后门, 需要写大量的Web层(Api. ...

  8. AutoMapper自动映射

    十年河东,十年河西,莫欺少年穷. 学无止境,精益求精. 不扯犊子,直接进入正题: AutoMapper自动映射常用于EF中,能很好的解决DTO和Model之间相互映射的问题.在未使用AutoMappe ...

  9. 常见Bean映射工具分析评测及Orika介绍

    原地址:http://tech.dianwoda.com/2017/11/04/gao-xing-neng-te-xing-feng-fu-de-beanying-she-gong-ju-orika/ ...

随机推荐

  1. 1、Dubbo-分布式系统定义

    1.分布式基础理论 1.1).什么是分布式系统? <分布式系统原理与范型>定义: “分布式系统是若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统” 分布式系统(distribu ...

  2. 解决Linux 安装python3 .5 解决pip 安装无法成功问题ssl安全拦截无法pip安装库问题

    pip is configured with locations that require TLS/SSL, however the ssl module in Python is not avail ...

  3. C语言函数指针 和 OC-Block

    C语言函数指针 和 OC-Block 一. C语言函数指针 关于函数指针的知识详细可参考:http://www.cnblogs.com/mjios/archive/2013/03/19/2967037 ...

  4. 学习使用 ARM 的 math 库,据说 速度比C标准库 自带的 快 几十倍 到几百倍

    1.首先 添加 库 到 工程 ,路径 如下 C:\Keil\ARM\CMSIS\Lib\ARM 2.包含头文件以及在 工程里 添加 头文件 路径如下  C:\Keil\ARM\CMSIS\Includ ...

  5. 将Spring容器跟随系统启动并获取容器对象

    将Spring容器随系统启动的方法: 在web.xml中配置监听器,监听的对象为ContextLoaderListener <listener> <listener-class> ...

  6. python 正则匹配手机号

    import rephone = str(input('请输入手机号:'))# b = str(12345678912)t = re.compile(r'^1(3\d|4[4-9]|5[0-35-9] ...

  7. canvas制作的烟花效果

    最近感觉canvas挺有意思的,在业余时间没事研究了一下,参考过网上一些思路,话不多说,开始啦. github地址:https://github.com/aWhiteBear/fireworks 演示 ...

  8. JDK1.8降到1.7技巧

    前言: 最近部署一个产品,该产品不支持JDK1.8,碰巧我的机器安装的是1.8,这就需要降到1.7才能部署启动成功.那么我也是不赞成卸载1.8来安装1.7,因为很多时候可能需要1.8和1.7来回切换. ...

  9. 偏前端-纯css,手写轮播-(焦点切换 和 自动轮播 只可选择一种,两者不可共存)

    现在我们一般都是在网上找个轮播插件,各种功能应有尽有,是吧!!~大家似乎已经生疏了手写是什么感觉.万一哪天想不起来,人家要手写,就尴尬了!~~跟我一起复习一下吧 不多说:效果图看一下: 高度不能是固定 ...

  10. 数据结构08——Trie

    一.什么是Trie? Trie树,一般被称为字典树.前缀树等等,Trie是一种多叉树,这个和二分搜索树.堆.线段树这些数据结构不一样,因为这些都是二叉树.,Trie树除了是一种多叉树,它是一种哈希树的 ...