实践是知识的母亲,知识是生活的明灯。这篇文章主要讲述ASP.NET Core 中的对象映射之 AutoMapper相关的知识,希望能为你提供帮助。
目录
- AutoMapper 简介
- AutoMapper 使用
- 初始化
- Profile设置
- 扁平化映射
- 集合映射
- 投影
- 条件映射
- 值转换
- 设置转换前后行为
- 配置验证及设置
- 反向映射
- 自定义转换器
- 自定义解析器
- 参考
AutoMapper 简介AutoMapper是一个对象映射器,它可以将一种类型的对象转换为另一种类型的对象。
【ASP.NET Core 中的对象映射之 AutoMapper】它提供了映射规则及操作方法,使我们不用过多配置就可以映射两个类, 可以帮我们免于编写无聊的映射代码. 在代码层与层之间隔离模型model上非常有用.
AutoMapper 使用 初始化创建两个简单的类用于测试:
public class UserEntity
{
public int Id { get;
set;
}
public string Name { get;
set;
}
}public class UserDTO
{
public int Id { get;
set;
}
public string Name { get;
set;
}
}
AutoMapper可以使用静态类和实例方法来创建映射.
- 静态类方式
Mapper.Initialize(cfg => cfg.CreateMap< UserEntity, UserDTO> ()); var userDTO = Mapper.Map< UserDTO> (user);
- 实例方式
var config = new MapperConfiguration(cfg => cfg.CreateMap< UserEntity, UserDTO> ()); var mapper = config.CreateMapper(); var userDTO = mapper.Map< UserDTO> (user);
- 依赖注入
使用扩展 AutoMapper.Extensions.Microsoft.DependencyInjection 来实现AutoMapper的依赖注入. 本质是注册一个MapperConfiguration的单例和IMapper的scope实例, 通过程序集扫描添加AutoMapper的相关配置和映射.
IServiceCollection services = new ServiceCollection(); services.AddAutoMapper(); var provider = services.BuildServiceProvider(); using (var scope = provider.CreateScope()) { var mapper = scope.ServiceProvider.GetService< IMapper> (); var userDTO = mapper.Map< UserDTO> (user); }
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
();
}
}var config = new MapperConfiguration(cfg =>
cfg.AddProfile<
UserProfile>
());
扁平化映射AutoMapper支持扁平化映射, 它会根据Pascal命名方式分割目标字段为单个单词, 可自动映射属性名+内嵌属性名. 如下例AutoMapper自动映射UserEntity.Address.City -> UserDTO.AddressCity。
public class UserEntity
{
public int Id { get;
set;
}
public string Name { get;
set;
}public Address Address { get;
set;
}
}public class Address
{
public string City { get;
set;
}
public string Country { get;
set;
}
}public class UserDTO
{
public int Id { get;
set;
}
public string Name { get;
set;
}
public string AddressCity { get;
set;
}
public string AddressCountry { get;
set;
}
}
集合映射AutoMapper除了可以映射单个对象外,也可以映射集合对象。
CreateMap<
UserEntity, UserDTO>
();
var userList = new List<
UserEntity>
{
new UserEntity { Id = 1, Name="Test1" },
new UserEntity { Id = 2, Name="Test2" },
};
var dtoList = mapper.Map<
List<
UserDTO>
>
(userList);
public class UserEntity
{
public int Id { get;
set;
}
public string Name { get;
set;
}public List<
AddressEntity>
AddressList { get;
set;
}
}public class AddressEntity
{
public string City { get;
set;
}
public string Country { get;
set;
}
}public class UserDTO
{
public int Id { get;
set;
}
public string Name { get;
set;
}public List<
AddressDTO>
AddressList { get;
set;
}
}public class AddressDTO
{
public string City { get;
set;
}
public string Country { get;
set;
}
}CreateMap<
AddressEntity, AddressDTO>
();
CreateMap<
UserEntity, UserDTO>
();
var user = new UserEntity
{
Id = 1,
Name = "Test",
AddressList = new List<
AddressEntity>
{
new AddressEntity { City = "ShangHai", Country = "China"},
new AddressEntity { City = "BeiJing", Country = "China"}
}
};
var userDTO = mapper.Map<
UserDTO>
(user);
投影当把一个源值投影到一个不精准匹配源结构的目标值时,使用MapFrom指明成员映射定义。
public class UserEntity
{
public int Id { get;
set;
}
public string Name { get;
set;
}
public DateTime BirthDate { get;
set;
}
}public class UserDTO
{
public int Id { get;
set;
}
public string Name { get;
set;
}
public string BirthYear { get;
set;
}
public string BirthMonth { get;
set;
}
}public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
()
.ForMember(d =>
d.BirthYear, o =>
o.MapFrom(s =>
s.BirthDate.Year))
.ForMember(d =>
d.BirthMonth, o =>
o.MapFrom(s =>
s.BirthDate.Month));
}
}var user = new UserEntity
{
Id = 1,
Name = "Test",
BirthDate = DateTime.Today,
};
var userDTO = mapper.Map<
UserDTO>
(user);
条件映射有些情况下,我们将只满足映射条件的才添加到属性上.
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
()
.ForMember(d =>
d.Id, o =>
o.Condition(s =>
s.Id >
1));
}
}
值转换AutoMapper可以配置值转换和空值替换
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
()
.ForMember(d =>
d.Name, o =>
o.NullSubstitute("Default Name"))
.ForMember(d =>
d.Name, o =>
o.AddTransform(val =>
string.Format("Name: {0}", val)));
}
}
设置转换前后行为有时候,在映射发生之前或之后,可能需要执行一些自定义的逻辑。
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
()
.BeforeMap((s, d) =>
s.BirthDate = s.BirthDate.AddYears(-12))
.AfterMap((s, d) =>
d.BirthMonth = "July");
}
}
配置验证及设置配置了映射,但是如何确定是否映射成功或者是否有字段没有映射呢?可以使用mapper.ConfigurationProvider.AssertConfigurationIsValid()来验证是否映射成功。但也可以指定单个字段不验证.
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
()
.ForMember(d =>
d.NickName, o =>
o.Ignore());
}
}
反向映射从6.1.0开始,AutoMapper通过ReverseMap可以实现反向映射。使用ReverseMap, 不用再创建DTO -> Entity的映射, 而且还能保留正向的映射规则。
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
()
.ReverseMap();
}
}
自定义转换器有些情况下目标字段类型和源字段类型不一致,可以通过类型转换器实现映射,类型转换器有三种实现方式:
void ConvertUsing(Func<
TSource, TDestination>
mappingFunction);
void ConvertUsing(ITypeConverter<
TSource, TDestination>
converter);
void ConvertUsing<
TTypeConverter>
() where TTypeConverter : ITypeConverter<
TSource, TDestination>
;
自定义解析器某些情况下,解析规则会很复杂,使用自带的解析规则无法实现。这时可以自定义解析规则,可以通过以下三种方式使用自定义的解析器:
ResolveUsing<
TValueResolver>
ResolveUsing(typeof(CustomValueResolver))
ResolveUsing(aValueResolverInstance)
public class UserEntity
{
public string FirstName { get;
set;
}
public string LastName { get;
set;
}
}public class UserDTO
{
public string Name { get;
set;
}
}public class UserNameResolver : IValueResolver<
UserEntity, UserDTO, string>
{
public string Resolve(UserEntity source, UserDTO destination, string destMember, ResolutionContext context)
{
if (source != null &
&
!string.IsNullOrEmpty(source.FirstName) &
&
!string.IsNullOrEmpty(source.LastName))
{
return string.Format("{0} {1}", source.FirstName, source.LastName);
}return string.Empty;
}
}public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<
UserEntity, UserDTO>
()
.ForMember(d =>
d.Name, o =>
o.ResolveUsing<
UserNameResolver>
());
}
}
参考
- automapper
- AutoMapper 使用总结
- http://www.cnblogs.com/farb/p/4932692.html
推荐阅读
- 针对APP的后台支付代码(微信和支付宝)
- uni-app调用原生的文件系统管理器(可选取附件上传)
- 对‘example_app_new’未定义的引用
- Android学习—— Android初级控件
- Go-内置函数之appendrecover用法
- XPath通配符
- XPath谓词
- XPath绝对路径
- XPath字符串函数