AutoMapper 是一个基于约定的面向对象的映射器,它的性能罕用于将一个 input 对象 转成一个不同类型的 output 对象,input 和 output 对象之间的属性可能雷同也可能不雷同,这一篇咱们来一起钻研一下 AutoMapper 的一些高级玩法。
装置 AutoMapper
要想在我的项目中应用 AutoMapper
,须要通过 nuget 援用 AutoMapper
和 AutoMapper.Extensions.Microsoft.DependencyInjection
包,能够通过 Visual Studio 2019 的 NuGet package manager
可视化界面装置 或者 通过 NuGet package manager
命令行工具输出以下命令:
Install-Package AutoMapper
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
配置 AutoMapper
一旦 AutoMapper 胜利装置之后,接下来就能够将它引入到 ServiceCollection 容器中,如下代码所示:
public void ConfigureServices(IServiceCollection services)
{services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAutoMapper(typeof(AuthorProfile));
}
应用 profiles 对立治理 mapping 信息
能够应用 profiles 来对立组织你的 mapping 信息,要创立 profile,须要实现 AutoMapper 提供的 Profile 类,而后在你方才创立的 Profile 子类的构造函数中增加映射信息,上面的代码展现了如何创立一个从 Proifle 继承的 AuthorProfile
类以及相干信息。
public class AuthorProfile : Profile
{public AuthorProfile()
{CreateMap<AuthorModel, AuthorDTO>();
}
}
接下来再看 AuthorModel 和 AuthorDTO 两个对象的定义:
public class AuthorModel
{
public int Id
{get; set;}
public string FirstName
{get;set;}
public string LastName
{get; set;}
public string Address
{get; set;}
}
public class AuthorDTO
{
public int Id
{get; set;}
public string FirstName
{get; set;}
public string LastName
{get; set;}
public string Address
{get; set;}
应用 ReverseMap()
值得注意的是,下面的示例是一种 单向流动
,这是什么意思呢?举个例子吧,上面是 单向流动
的一段代码。
AutoMapper.Mapper.CreateMap<AuthorDTO, AuthorModel>();
有了这个 Map,接下来就能够轻松实现 AuthorDTO 到 AuthorModel 的转换,代码如下:
var authorModel = AutoMapper.Mapper.Map<AuthorModel>(author);
假如因为某种原因,你须要将 authorModel 实例反转成 authorDTO,这时你用了如下的代码段。
var author = AutoMapper.Mapper.Map<AuthorDTO>(authorModel);
很遗憾,这种形式注定会抛出异样,这是因为 AutoMapper 并不知道如何实现 authorModel 到 authorDTO 的转换,毕竟你没有定义此种 map 的映射流向,那怎么解决呢?能够再定义一个 CreateMap 映射哈,其实没必要,简略粗犷的做法就是调用 ReverseMap
即可,实现代码如下:
AutoMapper.Mapper.CreateMap<AuthorDTO, AuthorModel>().ReverseMap();
应用 ForMember() 和 MapFrom()
这一节咱们持续应用之前说到的 AuthorModel 和 AuthorDTO 类,上面的代码片段展现了如何将 AuthorModel 转成 AuthorDTO。
var author = new AuthorModel();
author.Id = 1;
author.FirstName = "Joydip";
author.LastName = "Kanjilal";
author.Address = "Hyderabad";
var authorDTO = _mapper.Map<AuthorDTO>(author);
当初假如我将 AuthorModel 中的 Address 改成 Address1,如下代码所示:
public class AuthorModel
{
public int Id
{get; set;}
public string FirstName
{get; set;}
public string LastName
{get; set;}
public string Address1
{get; set;}
}
而后在 AuthorProfile 中更新一下 mapping 信息,如下代码所示:
public class AuthorProfile : Profile
{public AuthorProfile()
{CreateMap<AuthorModel, AuthorDTO>().ForMember(destination => destination.Address, map => map.MapFrom(source => source.Address1));
}
}
应用 NullSubstitute
何为 NullSubstitute
呢?粗心就是在映射转换的过程中,将 input 为 null 的属性映射之后做自定义解决,比方在 ouput 中改成 No Data
,上面的代码展现了如何去实现。
AutoMapper.Mapper.CreateMap<AuthorModel, AuthorDTO>().ForMember(destination => destination.Address, opt => opt.NullSubstitute("No data"));
mapping 的 AOP 拦挡
思考上面的两个类。
public class OrderModel
{public int Id { get; set;}
public string ItemCode {get; set;}
public int NumberOfItems {get; set;}
}
public class OrderDTO
{public int Id { get; set;}
public string ItemCode {get; set;}
public int NumberOfItems {get; set;}
}
能够应用 BeforeMap()
在 源对象 或者 指标对象 上执行一些计算或者初始化成员操作,上面的代码展现了如何去实现。
Mapper.Initialize(cfg => {cfg.CreateMap().BeforeMap((src, dest) => src.NumberOfItems = 0)
});
当 mapping 执行完之后,能够在 指标对象 上 安插 AfterMap()
办法,上面的代码展现了如何去实现。
public OrderDTO MapAuthor(IMapper mapper, OrderDTO orderDTO)
{
return mapper.Map<OrderModel, OrderDTO>(orderDTO, opt =>
{opt.AfterMap((src, dest) =>
{dest.NumberOfItems = _orderService.GetTotalItems(src);
});
});
}
应用嵌套映射
AutoMapper 同样也能够应用嵌套映射,思考上面的 domain 类。
public class Order
{public string OrderNumber { get; set;}
public IEnumerable<OrderItem> OrderItems {get; set;}
}
public class OrderItem
{public string ItemName { get; set;}
public decimal ItemPrice {get; set;}
public int ItemQuantity {get; set;}
}
接下来再看一下 DTO 类。
public class OrderDto
{public string OrderNumber { get; set;}
public IEnumerable<OrderItemDto> OrderItems {get; set;}
}
public class OrderItemDto
{public string ItemName { get; set;}
public decimal ItemPrice {get; set;}
public int ItemQuantity {get; set;}
}
最初看看如何在转换的过程中应用 mapping 的。
var orders = _repository.GetOrders();
Mapper.CreateMap<Order, OrderDto>();
Mapper.CreateMap<OrderItem, OrderItemDto>();
var model = Mapper.Map<IEnumerable<Order>, IEnumerable<OrderDto>>(orders);
AutoMapper 让你用最小化的配置实现了对象之间的映射,同时也能够实现自定义的解析器来实现具备齐全不同构造对象之间的映射,自定义解析器能够生成与指标对象具备雷同构造的 exchange,以便 AutoMapper 在运行时能够据其实现映射。
译文链接:https://www.infoworld.com/art…
更多高质量干货:参见我的 GitHub: csharptranslate