AutoMapper中的Map和DynamicMap——高手注重细节,思考和总结

简介:

近日在做项目的时候,遇到了个怪问题,关于AutoMapper的细节问题,也是不为一般人所关注的。

本人研究AutoMapper也没有多长时间,而且研究的过程中也写了关于AutoMapper的系列基础教程,但是毕竟AutoMapper是个开源项目,并不是一个简单的系列教程就能解释的清楚的,只能解释个大概,项目实战的时候,遇到的细节问题还得自己私下里再次研究、总结。

首先,我要说明的是,这篇博客的写作顺序是按事情发展的顺序来写的,也就是说,在我想写这篇博客时,问题的根本原因还没找到,但是此时,我回过头来,再来看这个过程中每个问题的解决思路,我想,此时这个细节的问题已经清楚了,也来分享一下。

 

先来让大家看看我的AutoMapper的大致配置过程:

  • 先创建实体类对应的AutoMapper配置类,命名规范是EntityName(实体类名)+Profile,比如PersonProfile,ProvincePerfile等。
复制代码
public class ProvinceProfile : Profile
{
    protected override void Configure()
    {
        Mapper.Initialize(cfg => cfg.CreateMap<Provinces, ProvinceDto>()
            .ForSourceMember(src=>src.UpdatedDate,opt=>opt.Ignore())
            .ReverseMap());
    }
}
复制代码
  • 再创建一个静态类,取名AutoMapperConfig,然后在他的静态方法中初始化Mapper,并添加所有的配置类,这里我还添加了其他配置类。
复制代码
public static class AutoMapperWebConfig
{
    public static void Configure()
    {
        Mapper.Reset();
        Mapper.Initialize(cfg =>
        {
            cfg.AddProfile<ProvinceProfile>();
            cfg.AddProfile<CityProfile>();
            cfg.AddProfile<StationProfile>();
            cfg.AddProfile<TerminalDeviceProfile>();//TerminalDeviceProfile依赖ProvinceProfile
            cfg.AddProfile<OperatorProfile>();  
        });
        Mapper.AssertConfigurationIsValid();//验证所有的映射配置是否都正常
    }
}
复制代码
  • 最后,在项目启动的时候(ASP.Net程序在.asax文件中的Application_Start方法)调用AutoMapperWebConfig.Configure();就可以了。

这一切都感觉这么顺利,但是往往越是顺利的时候,也意味着不顺快来了。接下来,类似下面截图中的错误向我狂轰乱炸。

当我使用在应用层使用Mapper.Map()方法将实体类映射为Dto类时,报错如下:

E{A2JHI%`4A68KE]KR6I_}3

很明显这是AutoMapper映射错误。

接下来就各种搜索错误,找到了下面一篇博客,原文

ta的解决方案是,如图

image

看到这里,我很高兴,赶紧改了一下自己的代码,发现果然成功了!但是该博主并没有给出个所以然来。

L]%SFP7IHKNLMU9V(_K}}{S

但是,我不服气,我之前已经创建了两个类之间的映射啊,为啥Mapper.Map()方法不行,我就纳闷了,我非得搞清楚这两者之间的关系不可。

我寻思着,就字面意思来看,一个是“映射”,一个是“动态映射”,会有啥区别呢?

于是各种搜两者之间的区别,去StackOverflow上找到了下面的答案:原链接

image

这里说,DynamicMap在编译时你不知道源类型的情况下使用,那么,相应地,Map就是在编译时知道源类型的情况下使用。简单的这一句解释并不能让接触AutoMapper时间不长的人有所启示。

而问题就出在,我之前已经创建了映射,所以在编译时应该可以确定源类型的,更何况我这两个类都很简单,不可能是因为数据类型不一致造成的映射失败啊!代码如下:

复制代码
public class Provinces : Entity
{
    public virtual string Code{ get; set; }

    public virtual string Name{ get; set; }
    public virtual string UpdatedBy{ get; set; }
    public virtual DateTime? UpdatedDate{ get; set; }
    public Provinces(){}
}
复制代码
复制代码
public class ProvinceDto:EntityDto
{
    public string Code { get; set; }
    public string Name { get; set; }
}
复制代码

 

于是,还得不到自己想要的答案,就去GitHub上AutoMapper的项目下Open了一个Issue,点击查看我提的Issue,在这里,我得到了我想要的答案。

image

该回答者给我的答案如上,他猜想我在每个实体类对应的Profile文件中,应该直接使用CreateMap,而不是在Mapper.Initialize中使用CreateMap。按照他的提示,我修改了代码,以后再也没有出现错误。

=============该总结了================

现在再次回头看看这个问题,完全是了然于胸的感觉。因为我在AutoMapperWebconfig静态类的静态方法中已经进行了Mapper.Initialize(),这是AutoMapper的初始化,而在每个实体类对应的Profile类中又使用了一次。尝试着去想一想,第一次将所有的文配置类都初始化到Mapper(暂且先将它理解成一个容器)中,第二次调用Mapper.Initialize()可能会把之前的内容都擦除掉,所以使用Mapper.Map的时候会报错就可以想明白了,而使用DynamicMap,之前在哪里看到过DynamicMap就想当于先CreateMap,再Map,所以,我们之前的配置就可有可无,无关紧要了,因为DynamicMap会把之前的配置擦除掉,所以上面截图中的映射成功了。而至于其他配置类没有出现该错误,该回答者给的答案是”这可能是个意外!“。在这次坎坷曲折的解决问题的过程中,还是学到了很多东西的。在这里,我们也很显然,可以看出博客园那位园友使用DynamicMap成功后而没给出为什么,十有八九也是我这个问题了。






本文转自tkbSimplest博客园博客,原文链接:http://www.cnblogs.com/farb/p/4995431.html,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
C++
C++ 数据封装的方法,重点是其编程思想
在C++中,数据封装一般指的是将数据和操作这些数据的函数绑定在一起的程序设计方式。通常使用C++的类来实现
36 7
|
4月前
|
SQL 缓存 Java
Mybatis源码细节探究:MappedStatement和Cache对象对照关系研究
Mybatis源码细节探究:MappedStatement和Cache对象对照关系研究
|
11月前
|
存储 编译器 C++
【C++】list迭代器的深度剖析及模拟实现(感受类封装,类和对象的思想)
【C++】list迭代器的深度剖析及模拟实现(感受类封装,类和对象的思想)
|
JSON Java fastjson
阿粉带你彻底解决开发中对象Bean与Map互转问题!
在实际开发过程中,经常碰到需要进行对象与map之间互转的问题,其实对于对象、Map 之间进行互转有很多种方式,下面我们一起来梳理一下:
1071 0
阿粉带你彻底解决开发中对象Bean与Map互转问题!
|
前端开发 Java 程序员
struts2封装好的三种收参方式,零散、对象、集合。
struts2封装好的三种收参方式,零散、对象、集合。
72 0
struts2封装好的三种收参方式,零散、对象、集合。
|
存储 JSON 自然语言处理
悟透前端 | ECMAScript 6 的 Map 映射
映射(Map)是 ECMAScript 6 规范中引入的一种数据结构。这是一种存储键值对列表很方便的方法,类似于其他编程语言中的词典或者哈希表。
81 0
|
存储 JSON 自然语言处理
悟透前端 | ECMAScript 6的Map映射
映射(Map)是 ECMAScript 6 规范中引入的一种数据结构。这是一种存储键值对列表很方便的方法,类似于其他编程语言中的词典或者哈希表。让我们一起来看一下映射这种数据结构。
215 0
悟透前端 | ECMAScript 6的Map映射
|
设计模式 Java
教你借助设计模式限制实例化数量 | 带你学《Java面向对象编程》之七十三
开发过程中,如果遇到了某些要求,需要限制实例化类的数量时,需要借助本节介绍到的单例与多例设计模式来实现。
教你借助设计模式限制实例化数量   | 带你学《Java面向对象编程》之七十三
比较无处不在-灵活覆写equals方法 | 带你学《Java面向对象编程》之五十一
本节通过对比简单比较的实现代码与覆写Object类的比较方法实现比较逻辑,体现了Java精益求精的理念。