zoukankan      html  css  js  c++  java
  • 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成功后而没给出为什么,十有八九也是我这个问题了。

    ==============总结完毕================

  • 相关阅读:
    如何免费做一个属于自己稳定有效的图床
    关于自己每日计划是如何制定的
    记一次买4K显示器的心酸历程
    Mac常用的软件推荐
    2019 一整年的总结与一些个人反思
    Lucene学习笔记: 五,Lucene搜索过程解析
    Lucene学习笔记: 四,Lucene索引过程分析
    lucene学习笔记:三,Lucene的索引文件格式
    lucene学习笔记:二,Lucene的框架
    Lucene学习笔记:一,全文检索的基本原理
  • 原文地址:https://www.cnblogs.com/farb/p/4995431.html
Copyright © 2011-2022 走看看