网上关于abp框架的学习的文章很多。本文大部分也是摘自其他作者的文章。 官方api文档:https://aspnetboilerplate.com/api-docs/html/N_Abp_AutoMapper.htm
Mapper.CreateMap<<CreateNoteDto, Note>>();
使用
Note note = Mapper.Map<Note>(CreateNoteDto);
偶尔有时候,在映射发生之前或之后,你可能需要执行一些自定义的逻辑。这可能是很少见的事情,因为在AutoMapper之外处理这些事情是更明显的。你可以创建一个映射前后的全局操作:
Mapper.CreateMap<Source, Dest>()
.BeforeMap((src, dest) => src.Value = src.Value + 10)
.AfterMap((src, dest) => dest.Name = "John");
在属性映射之前,AutoMapper允许将必须满足的条件添加到属性上。
//创建映射,映射条件是源类型的Age属性在区间(0,149)范围内
Mapper.CreateMap<Aliens, Person>().ForMember(dest => dest.Age, opt => opt.Condition(src => src.Age > 0 && src.Age < 149));
初始化是配置AutoMapper受人欢迎的模式,每个应用域应该配置一次:
//初始化配置文件
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Aliens, Person>();
cfg.AddProfile<AliensPersonProfile>();//添加一个配置文件
});
自定义一个继承了Profile类的类,然后重写Configure方法,在该方法中放一些映射的配置。这个在我们建立的.net core项目中会看见
public class NoteMapProfile : Profile
{
public NoteMapProfile()
{
CreateMap<CreateNoteDto, Note>();
}
}
有时,需要完全控制一个类型到另一个类型的转换。一个类型一点都不像另一个类型,而且转换函数已经存在了,在这种情况下,你想要从一个“宽松”的类型转换成一个更强壮的类型,例如一个string的源类型到一个int32的目标类型。
这里有两个类Source和Destination,要把前者映射到后者,代码如下:
public class Source
{
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
}
public class Destination
{
public int Value1 { get; set; }
public DateTime Value2 { get; set; }
public Type Value3 { get; set; }
}
public class CustomTypeConverter : ITypeConverter<Source, Destination>
{
public Destination Convert(ResolutionContext context)
{
Source src = context.SourceValue as Source;
var dest = new Destination
{
Value1 = System.Convert.ToInt32(src.Value1),
Value2 = System.Convert.ToDateTime(src.Value2),
Value3 = context.SourceType
};
return dest;
}
}
Mapper.CreateMap<Source, Destination>().ConvertUsing<CustomTypeConverter>();
虽然AutoMapper覆盖了相当一部分目标成员的映射场景,但是还有 1-5%的目标值需要解析处理一下。很多时候,自定义的值解析是可以放在领域层的领域逻辑。然而,如果该逻辑只是和映射操作有关的话,那它就会应为一些不必要的行为使得源类型很凌乱。这种场合,AutoMapper允许我们为目标成员配置自定义的值解析器。 我们可以实现抽象类ValueResolver<TSource, TDestination>来实现自定义值解析。例如:
/// <summary>
/// 文章信息
/// </summary>
public class Note
{
/// <summary>
/// 是否发布
/// </summary>
public bool IsPublic { get; set; }
}
/// <summary>
/// 用于列表展示
/// </summary>
public class NoteDto
{
/// <summary>
/// 是否发布
/// </summary>
public string IsPublic { get; set; }
}
public class NoteToNoteDtoResolver : IValueResolver<Note, NoteDto, string>
{
public string Resolve(Note source, NoteDto destination, string destMember, ResolutionContext context)
{
return source.IsPublic ? "已发布" : "未发布";
}
}
CreateMap<Note, NoteDto>().ForMember(x=>x.IsPublic,opt=> {
opt.ResolveUsing<NoteToNoteDtoResolver>();
});
测试结果
因为我们只提供了自定义的解析器类型给AutoMapper,所以映射引擎会使用反射创建该值解析器的实例。如果我们不想要AutoMapper使用反射创建实例,我们要么直接提供一个实例,要么使用ConstruceBy方法来提供一个自定义的构造函数方法。在映射操作期间,AutoMapper不使用反射,直接执行此回调函数:
Mapper.CreateMap<Source, Destination>().ForMember(dest => dest.Total, opt =>
{
opt.ResolveUsing<MyValueResolver>().ConstructedBy(()=>new MyValueResolver());
});