ABP中的AutoMapper

陌路散爱 提交于 2019-11-29 00:19:32

  在我们的业务中经常需要使用到类型之间的映射,特别是在和前端页面进行交互的时候,我们需要定义各种类型的Dto,并且需要需要这些Dto和数据库中的实体进行映射,对于有些大对象而言,需要赋值太多的属性,这样往往会使整个代码不够简洁和明了,有了AutoMapper之后我们就可以通过很少的代码来完成这样一个映射的过程,在了解当前的代码之前,你最好先读一下ABP文档中对于这个部分的介绍。

  一 用法

  1 注入IObjectMapper接口

  通过接口注入IObjectMapper对象,如果使用ABP框架的话所有继承自ApplicationService的应用服务都可以获取定义于AbpServiceBase中已经注入的公用属性ObjectMapper对象。

  2 定义映射关系

  在当前继承自AbpModule的类下面的Initialize()方法中添加映射关系

public override void Initialize() {
            IocManager.RegisterAssemblyByConvention(typeof(DcsApplicationModule).GetAssembly());
            IocManager.AddSdtSession<Guid>();

            Configuration.Modules.AbpAutoMapper().Configurators.Add(config => {
                config.CreateMissingTypeMaps = true;
                
                #region 客户售后档案,客户售后档案与车辆关系

                config.CreateMap<CustomerSoldDto, CustomerSold>(MemberList.Source);
                config.CreateMap<CustomerVehicleSoldDto, CustomerVehicleSold>(MemberList.Source);
                config.CreateMap<CustomerSoldExtendedInput, CustomerSoldExtended>(MemberList.Source)
                    .ForMember(c => c.C4cmCode, o => o.MapFrom(m => m.CrmCode))
                    .ForMember(c => c.ReferrerPhone, o => o.MapFrom(m => m.Referrer));
                config.CreateMap<CustomerSoldSyncInput, CustomerSold>(MemberList.Source)
                    .ForMember(c => c.CustomerSoldExtended, o => o.MapFrom(m => m.CustomerSoldExtended))
                    .ForMember(c => c.JobName, o => o.MapFrom(m => m.JobTitle));

                #endregion 客户售后档案,客户售后档案与车辆关系               
            });
        }

  上面的代码中我们可以使用ForMember方法来定义自己的映射规则。

  3 使用ObjectMapper映射实体关系

  在有了第一步的工作后,我们就可以在业务代码中调用_objectMapper.Map<T>(input),或者是_objectMapper.Map(input,oldEntity)这种方式来实现从Dto到数据库实体的映射关系。

  二 注意事项

  1 定义Profile来分散映射关系

  如果我们把所有的映射关系都写在Module的Initialize()方法里面,我们发现对于一个大的项目简直就是一个灾难,因为这个映射关系实在是太多,整个类超级大,现在有一个解决方案就是定义自己的XXXProfile,但是需要继承自基类Profile类。

public class EngineMaintainApplyProfile : Profile {
        public EngineMaintainApplyProfile() {
            CreateMap<EngineMaintainApply, QueryEngineMaintainApplyOutput>(MemberList.Destination)
                .ForMember(d => d.BreakMaintainMark, options => options.MapFrom(s => s.VehicleSold.BreakMaintainMark));

            CreateMap<EngineMaintainApplyAth, EngineMaintainApplyAthDto>(MemberList.Destination);
            CreateMap<EngineMaintainApply, QueryEngineMaintainApplyWithDetailsOutput>(MemberList.Destination)
                .ForMember(d => d.Attachments, options => options.MapFrom(s => s.EngineMaintainApplyAths))
                .ForMember(d => d.ProductCode, options => options.MapFrom(s => s.VehicleSold.ProductCode))
                .ForMember(d => d.EngineCode, options => options.MapFrom(s => s.VehicleSold.EngineCode))
                .ForMember(d => d.TransmissionSn, options => options.MapFrom(s => s.VehicleSold.TransmissionSn))
                .ForMember(d => d.Color, options => options.MapFrom(s => s.VehicleSold.Color))
                .ForMember(d => d.VehiclePurpose, options => options.MapFrom(s => s.VehicleSold.VehiclePurpose))
                .ForMember(d => d.InvoiceDate, options => options.MapFrom(s => s.VehicleSold.InvoiceDate))
                .ForMember(d => d.SalePrice, options => options.MapFrom(s => s.VehicleSold.SalePrice))
                .ForMember(d => d.ProductionDate, options => options.MapFrom(s => s.VehicleSold.ProductionDate))
                .ForMember(d => d.VehicleSaleDate, options => options.MapFrom(s => s.VehicleSold.SaleDate));

            CreateMap<AddEngineMaintainApplyInput, EngineMaintainApply>(MemberList.Source)
                .ForMember(d => d.VehicleSoldId, options => options.MapFrom(s => s.VehicleId))
                .ForMember(d => d.ExtensionMaintainBeginDate, options => options.MapFrom(s => s.SaleDate))
                .ForMember(d => d.EngineMaintainApplyAths, options => options.Ignore());

            CreateMap<UpdateEngineMaintainApplyInput, EngineMaintainApply>(MemberList.Source)
                .ForMember(d => d.RowVersion, options => options.Ignore())
                .ForMember(d => d.EngineMaintainApplyAths, options => options.Ignore());
        }
    }

  使用这个方法的时候需要注意需要在Initialize方法里面添加映射,例如下面的方式。

public override void Initialize() {
            IocManager.RegisterAssemblyByConvention(typeof(DcsApplicationModule).GetAssembly());           

            Configuration.Modules.AbpAutoMapper().Configurators.Add(config => {                
               config.AddMaps(typeof(DcsApplicationModule).GetAssembly());                             
            });
        }

  2 添加自动映射关系

  这个需要特别注意,当我们的Dto和目标实体每个字段都能一一对应的情况下,在AutoMapper<8.1.1这个版本的时候能够自动识别并映射,但是当升级到这个版本的时候这个特性会去掉,AutoMapper的官方暂时给了一个过渡的方案,那就是设置CreateMissingTypeMaps属性设置为true,就像下面的例子。

public override void Initialize() {
            IocManager.RegisterAssemblyByConvention(typeof(DcsApplicationModule).GetAssembly());            

            Configuration.Modules.AbpAutoMapper().Configurators.Add(config => {                
                config.CreateMissingTypeMaps = true;
            });
        }

  但是这只是一个过渡方案,在这个属性的上面加了一个Obsolete标签,并说明在Version9.0的时候会去掉,所以后面我们也是需要去显式去添加映射关系。

 /// <summary>
        /// Create missing type maps during mapping, if necessary
        /// </summary>
        [Obsolete("Support for automatically created maps will be removed in version 9.0. You will need to explicitly configure maps, manually or using reflection. Also consider attribute mapping (http://docs.automapper.org/en/latest/Attribute-mapping.html).")]
        bool ? CreateMissingTypeMaps { get; set; }

  

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!