demo 地址:
该文章是系列文章 基于. NetCore 和 ABP 框架如何让 Windows 服务执行 Quartz 定时作业 的其中一篇.
AutoMapper 简介
AutoMapper 是一个简单的小型的对象映射库, 是为了解决一个繁杂的问题 - 将一个对象映射到另一个对象的到处乱飞的胶水代码. 这类胶水代码非常沉闷, 让人怀疑自己的工作的价值性. AutoMapper 就是你摆脱此类代码的福音.
官网地址: https://automapper.org/
GitHub 地址: https://github.com/AutoMapper/AutoMapper
AutoMapper 的简单使用
这里拿官网的例子做一个简单说明, 主要是为了引出在 Abp 中是如何使用的, 来进行对比. 使用 AutoMapper 将遇到的最经典的两个场景.
最多遇到的场景, 应该是接口返回的 DTO 和数据库 Entity, 出于敏感信息保护或者减少接口返回数据等等的原因, DTO 返回的属性或者字段有所删减, 也就是说需要映射的属性或者字段属性名称一致.
DTO 和 Entity 名称不一致, 甚至类型不同, 相互转换时甚至需要对数据有处理.
下面的例子就是字段属性基本一致.
- public class Order
- {
- public string OrderName { get;set; }
- public string PhoneNumber { get;set; }
- }
- public class OrderDto
- {
- public string OrderName { get;set; }
- }
- var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());
- var mapper = config.CreateMapper();
- OrderDto dto = mapper.Map<OrderDto>(order);
或者
- var config = new MapperConfiguration(cfg => cfg.CreateMap<Order, OrderDto>());
- var mapper = new Mapper(config);
- OrderDto dto = mapper.Map<OrderDto>(order);
Abp.AutoMapper 的简单使用
Abp.AutoMapper 的官网文档:
Abp.AutoMapper 的 Nuget 地址: https://www.nuget.org/packages/Abp.AutoMapper
添加 nuget 包
Install-Package Abp.AutoMapper
添加 AbpAutoMapperModule 模块
- [DependsOn(typeof(AbpAutoMapperModule))]
- public class MyJobCoreModule : AbpModule
- {
- }
指定映射关系
自动映射
你可以通过属性 AutoMap, AutoMapFrom, AutoMapTo 指定映射关系
改造上面的之前的例子
- [AutoMapFrom(typeof(Order))]
- public class OrderDto
- {
- public string OrderName { get;set; }
- }
或者
- [AutoMapTo(typeof(OrderDto))]
- public class Order
- {
- public string OrderName { get;set; }
- public string PhoneNumber { get;set; }
- }
但是属性的使用场景比较窄, 稍微复杂一点的场景就无法满足, 比如, 指定忽略一些字段, 或者字段名称不同需要显示指定.
自定义映射
- [DependsOn(typeof(AbpAutoMapperModule))]
- public class MyJobCoreModule : AbpModule
- {
- public override void PreInitialize()
- {
- Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>
- {
- config.CreateMap<Order, OrderDto>();
- });
- }
- }
忽略字段
- config.CreateMap<Order, OrderDto>()
- .ForMember(u => u.PhoneNumber, options => options.Ignore());
字段名不一致
OrderDto 增加手机号字段 Tel, 映射 Order 字段 PhoneNumber
- public class OrderDto
- {
- public string OrderName { get; set; }
- public string Tel { get; set; }
- }
- config.CreateMap<Order, OrderDto>()
- .ForMember(u => u.Tel, options => options.MapFrom(input => input.PhoneNumber));
需要对字段进行处理后返回
比如, 隐藏 11 位手机号的中间 4 位
- private static string HideTel(string input)
- {
- if (string.IsNullOrEmpty(input))
- {
- return string.Empty;
- }
- var outReplace = Regex.Replace(input, "(\\d{3})\\d{4}(\\d{4})", "$1****$2");
- return outReplace;
- }
- config.CreateMap<Order, OrderDto>()
- .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.PhoneNumber)));
拼接映射
又比如 OrderDto 新增邮寄地址和收货地址
- namespace Demo.MyJob.Entity.Dto
- {
- public class OrderDto
- {
- public string OrderName { get; set; }
- public string Tel { get; set; }
- public string PostalAddress { get; set; }
- public string DeliveryAddress { get; set; }
- }
- }
Order 的相关表 OrderAddress 类型定义
- namespace Demo.MyJob.Entity
- {
- public class OrderAddress
- {
- public string OrderId { get; set; }
- public string PostalAddress { get; set; }
- public string DeliveryAddress { get; set; }
- }
- }
这时就需要 OrderAddress 和 Order 的数据相结合映射 OrderDto, 怎么实现呢? 借助元组 Tuple.
- config.CreateMap<(Order, OrderAddress), OrderDto>()
- .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.Item1.PhoneNumber)))
- .ForMember(u => u.OrderName, options => options.MapFrom(input => input.Item1.OrderName))
- .ForMember(u => u.PostalAddress, options => options.MapFrom(input => input.Item2.PostalAddress))
- .ForMember(u => u.DeliveryAddress, options => options.MapFrom(input => input.Item2.DeliveryAddress))
- ;
精简配置
需要自定义的映射关系过多时, 会使得 PreInitialize 变大, 不便于管理和查看.
- public override void PreInitialize()
- {
- Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>
- {
- config.CreateMap<(Order, OrderAddress), OrderDto>()
- .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.Item1.PhoneNumber)))
- .ForMember(u => u.OrderName, options => options.MapFrom(input => input.Item1.OrderName))
- .ForMember(u => u.PostalAddress, options => options.MapFrom(input => input.Item2.PostalAddress))
- .ForMember(u => u.DeliveryAddress, options => options.MapFrom(input => input.Item2.DeliveryAddress))
- ;
- });
- }
如何精简? 新增类型 MyMapperProfile, 继承 AutoMapper.Profile
- using System.Text.RegularExpressions;
- using AutoMapper;
- using Demo.MyJob.Entity;
- using Demo.MyJob.Entity.Dto;
- namespace Demo.MyJob.MapperProfiles
- {
- class MyMapperProfile : Profile
- {
- private static string HideTel(string input)
- {
- if (string.IsNullOrEmpty(input))
- {
- return string.Empty;
- }
- var outReplace = Regex.Replace(input, "(\\d{3})\\d{4}(\\d{4})", "$1****$2");
- return outReplace;
- }
- public MyMapperProfile()
- {
- CreateMap<Order, OrderDto>()
- .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.PhoneNumber)));
- CreateMap<(Order, OrderAddress), OrderDto>()
- .ForMember(u => u.Tel, options => options.MapFrom(input => HideTel(input.Item1.PhoneNumber)))
- .ForMember(u => u.OrderName, options => options.MapFrom(input => input.Item1.OrderName))
- .ForMember(u => u.PostalAddress, options => options.MapFrom(input => input.Item2.PostalAddress))
- .ForMember(u => u.DeliveryAddress, options => options.MapFrom(input => input.Item2.DeliveryAddress))
- ;
- }
- }
- }
修改 PreInitialize
- [DependsOn(typeof(AbpAutoMapperModule))]
- public class MyJobCoreModule : AbpModule
- {
- public override void PreInitialize()
- {
- Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>
- {
- config.AddMaps(typeof(MyJobCoreModule));
- });
- }
- }
Abp.AutoMapper 版本低于 4.8.0 的可以修改为
config.AddProfiles(typeof(MyJobCoreModule));
以上就是如何在 Abp 框架下灵活使用 AutoMapper 的全部内容, 谢谢阅读.
来源: https://www.cnblogs.com/AlienXu/p/Abp_AutoMapper.html