Dotnet Core中使用AutoMapper
文档:https://automapper.readthedocs.io/en/latest/index.html
GitHub:https://github.com/AutoMapper/AutoMapper/blob/master/docs/index.rst
什么是AutoMapper?
AutoMapper是一个对象-对象映射器。对象-对象映射通过将一种类型的输入对象转换为另一种类型的输出对象来工作。使AutoMapper变得有趣的是,它提供了一些有趣的约定,以免去搞清楚如何将类型A映射为类型B。只要类型B遵循AutoMapper既定的约定,就需要几乎零配置来映射两个类型。
为什么要使用AutoMapper?
映射代码很无聊。测试映射代码更加无聊。AutoMapper提供了简单的类型配置以及简单的映射测试。真正的问题可能是“为什么使用对象-对象映射?”映射可以在应用程序中的许多地方发生,但主要发生在层之间的边界中,例如UI /域层或服务/域层之间。一层的关注点通常与另一层的关注点冲突,因此对象-对象映射导致分离的模型,其中每一层的关注点仅会影响该层中的类型。
AutoMapper的使用场景:
AutoMapper是对象到对象的映射工具。在完成映射规则之后,AutoMapper可以将源对象转换为目标对象。
一般情况下,表现层与应用层之间是通过DTO(数据传输对象Data Transfer Object)来进行交互的,数据传输对象是没有行为的POCO对象(简单CLR对象Plain Old CLR Object),他的目的是为了对领域对象进行数据封装,实现层与层之间的数据传递。为何不直接将领域对象进行数据传递?因为领域对象更注重领域,DTO更注重数据。由于“富领域模型”的特点,这样会直接将领域对象的行为暴露给表现层。
DTO本身不是业务对象,它是根据UI需求进行设计的。简单来说Model面向业务,我们是通过业务来定义Model的。而DTO是面向UI,通过UI的需求来定义的,通过DTO我们实现了表现层与Model层之间的解耦,表现层不引用Model。如果开发过程中我们的模型变了,而界面没变,我们只需改Model而不需要去改动表现层。
如何使用AutoMapper?
首先,您需要同时使用源类型和目标类型。目标类型的设计可能会受到其所在层的影响,但是只要成员名称与源类型的成员匹配,AutoMapper的效果最佳。如果您有一个名为“ FirstName”的源成员,它将自动映射到名称为“ FirstName”的目标成员。AutoMapper还支持Flattening。
将源映射到目标时,AutoMapper将忽略空引用异常。这是设计使然。如果您不喜欢这种方法,则可以根据需要将AutoMapper的方法与自定义值解析器结合使用。
如何在Dotnet Core中使用AutoMapper?
首先,要安装依赖包:
在Startup.cs中利用Dotnet Core自带的容器进行注入,因为我里面是示例代码,新建的示例Demo也没有去改名字,也都是在同一个命名空间下的,但是在实际项目中是不会出现这种问题的
//添加对AutoMapper的支持 services.AddAutoMapper(Assembly.Load("WebApplication1"), Assembly.Load("WebApplication1"));
即下图所示的关系:
源类型Model对象,与映射后的DTO类型:
public class UserInfo { public string UserName { get; set; } public string UserPwd { get; set; } public string GetCreateTime { get; set; } }
public class UserInfoDTO { public string UserName { get; set; } public string UserPwd { get; set; } public string Role { get; set; } public DateTime CreateTime { get; set; } public string TestTime { get; set; } }
Profile的用法:
Profile提供了一个命名的映射类,所有继承自Profile类的子类都是一个映射集合。这里我们创建一个UserProfile继承Profile类。
CreateMap:创建映射规则。
BeforeMap:在映射之前执行的方法。
AfterMap:反之,映射之后执行的方法。
自动化扁平映射:AutoMapper会将类中的属性进行分割,或匹配"Get"开头的方法。
ForMember:指定映射字段。
public class UserProfile : Profile { //添加你的尸体映射关系 public UserProfile() { CreateMap<UserInfo, UserInfoDTO>() .BeforeMap((source, dto) => { //可以较为精确的控制输出数据格式 if (string.IsNullOrEmpty(source.GetCreateTime)) { source.GetCreateTime = Convert.ToDateTime(source.GetCreateTime).ToString("yyyy-MM-dd"); } }) //指定映射字段。将UserInfo.GetCreateTime映射到UserInfoDTO.TestTime .ForMember(dto => dto.TestTime, opt => opt.MapFrom(info => info.GetCreateTime)) .ForMember(dto => dto.Role, opt => opt.Ignore()) .ForMember(dto => dto.CreateTime, opt => opt.Ignore()); CreateMap<StudentInfo, UserInfo>(); } }
控制器注入IMapper:
private readonly IMapper _mapper; public HomeController(IMapper mapper) { _mapper = mapper; }
单个对象转DTO:
//模拟数据 var user = new UserInfo() { UserName = "bingle", UserPwd = "12345" }; var userDto = _mapper.Map<UserInfoDTO>(user);
集合转Dto集合:
//模拟数据 var userList = new List<UserInfo> { new UserInfo { UserName="bingle_1", UserPwd="1" }, new UserInfo { UserName="bingle_2", UserPwd="2" }, new UserInfo { UserName="bingle_3", UserPwd="3" }, new UserInfo { UserName="bingle_4", UserPwd="4" }, new UserInfo { UserName="bingle_5", UserPwd="5" }, new UserInfo { UserName="bingle_6", UserPwd="6" } }; //对象集合转Dto集合 var usersDtos = _mapper.Map<List<UserInfoDTO>>(userList);
AutoMapper功能很强大,在这边介绍的只是很少的功能,有兴趣的伙伴可以去AutoMapper官方文档深入学习。
如果有小伙伴觉得在使用AutoMapper都得在Controller的构造函数中进行注入一遍麻烦的话,AutoMapper也是支持这种映射方式如:Mapper.Map
实例方式:
//模拟数据 var user = new UserInfo() { UserName = "bingle", UserPwd = "12345" }; var config = new MapperConfiguration(cfg => cfg.CreateMap<UserInfo, UserInfoDTO>()); var mapper = config.CreateMapper(); var userDTO = mapper.Map<UserInfoDTO>(user);
参考:https://blog.csdn.net/weixin_37207795/article/details/81009878