(注:本文示例使用的是.NET Core 3.1)
1. 配置 (Configuration)
Reference: https://docs.automapper.org/en/latest/Configuration.html
多种方法配置,这里推荐使用配置文件实例 (Profile Instances)。创建继承自Profile
并将配置放入构造函数的类。
1.1 安装NuGet包:
Install-Package AutoMapper -Version 11.0.1
1.2 新建Profile Instance:
// This is the approach starting with version 5
public class MyAppProfile : Profile
{
public MyAppProfile()
{
CreateMap<Source, Destination>();
// Use CreateMap... Etc.. here
}
}
2. 依赖注入 (Dependency Injection)
Reference: https://docs.automapper.org/en/latest/Dependency-injection.html
1)安装NuGet包
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection -Version 11.0.0
2)添加到StartUp的ConfigureServices
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// Add auto mapper
services.AddAutoMapper(typeof(MyAppProfile));
// services.AddAutoMapper(typeof(ProfileTypeFromAssembly));
// services.AddAutoMapper(typeof(ProfileTypeFromAssembly1), typeof(ProfileTypeFromAssembly2) /*, ...*/);
}
3)将 AutoMapper 注入services / controllers:
public class HomeController : ControllerBase
{
private readonly IMapper _mapper;
public HomeController(IMapper mapper)
{
_mapper = mapper;
}
}
3. 重写配置 (Override configuration)
3.1 使用 Ignore()
目标类型有个属性Xxx,跳过 Map 操作。
CreateMap<Source, Destination>()
.ForMember(d => d.Xxx, opt => opt.Ignore());
3.2 空替换 (Null Substitution)
Reference: https://docs.automapper.org/en/latest/Null-substitution.html
空替换允许您为目标属性提供替代值。这意味着它不会从 null 映射,而是从你提供的值映射。
CreateMap<Source, Destination>()
.ForMember(d => d.Xxx, opt => opt.NullSubstitute("Other Value"));
3.3 自定义 (MapFrom)
Reference: https://docs.automapper.org/en/latest/Projection.html
CreateMap<Source, Destination>()
.ForMember(d => d.ValueLength, opt => opt.MapFrom(s => s != null ? s.Value.Length : 0));
3.4 条件映射 (Conditional Mapping)
Reference: https://docs.automapper.org/en/latest/Conditional-mapping.html
AutoMapper 允许将条件添加到在映射该属性之前必须满足的属性。
在下面的映射中,属性 Baz 只有在源对象中大于或等于 0 时才会被映射。
CreateMap<Source, Destination>()
.ForMember(d => d.Baz, opt => opt.Condition(s => (s.Baz >= 0)));
3.5 前提条件 (Preconditions)
Reference: https://docs.automapper.org/en/latest/Conditional-mapping.html#preconditions
同样,还有一个 PreCondition 方法。不同之处在于它在映射过程中运行得更快,在解析源值之前(想想 MapFrom)。所以先决条件被调用,然后我们决定哪个是映射(解析)的源,然后调用条件,最后分配目标值。
CreateMap<Source, Destination>()
.ForMember(d => d.Baz, opt => {
opt.PreCondition(s => (s.Baz >= 0));
opt.MapFrom(s => {
// Expensive resolution process that can be avoided with a PreCondition
});
});
4. 支持列表和数组映射 (Lists and Arrays)
Reference: https://docs.automapper.org/en/latest/Lists-and-arrays.html
支持的源集合类型包括:
- IEnumerable
- IEnumerable
- ICollection
- ICollection
- IList
- IList
- List
- Arrays
5. 支持嵌套映射 Nested Mappings
Reference: https://docs.automapper.org/en/latest/Nested-mappings.html
当映射引擎执行映射时,它可以使用多种方法之一来解析目标成员值。其中一种方法是使用另一种类型映射,其中源成员类型和目标成员类型也在映射配置中进行配置。这使我们不仅可以扁平化我们的源类型,还可以创建复杂的目标类型。例如,我们的源类型可能包含另一个复杂类型:
public class Source
{
public int Value { get; set; }
public InnerSource Inner { get; set; }
}
public class InnerSource
{
public int OtherValue { get; set; }
}
public class Destination
{
public int Value { get; set; }
public InnerDestination Inner { get; set; }
}
public class InnerDestination
{
public int OtherValue { get; set; }
}
在这种情况下,配置类型映射:
CreateMap<Source, Destination>();
CreateMap<InnerSource, InnerDestination>();
【注意】:
- 配置类型的顺序无关紧要
- 调用 Map 不需要指定任何内部类型映射,只需要指定用于传入的源值的类型映射
6. 示例:
Class:
public class Student
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Nickname { get; set; }
public int? Age { get; set; }
public DateTime UpdatedDate { get; set; }
public string AddressId { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public string Id { get; set; }
public string PostalCode { get; set; }
public string Block { get; set; }
public string Street { get; set; }
public string Floor { get; set; }
public string Unit { get; set; }
public string Building { get; set; }
}
public class StudentDto
{
public string Id { get; set; }
public string FullName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Nickname { get; set; }
public int? Age { get; set; }
public DateTime CreatedDate { get; set; }
public string PostalCode { get; set; }
public string AddressStreet { get; set; }
public AddressDto Address { get; set; }
}
public class AddressDto
{
public string PostalCode { get; set; }
public string Block { get; set; }
public string Street { get; set; }
public string Floor { get; set; }
public string Unit { get; set; }
public string Building { get; set; }
}
Profile:
public class MyAppProfile : Profile
{
public MyAppProfile()
{
CreateMap<Student, StudentDto>()
.ForMember(d => d.Nickname, opt => opt.NullSubstitute("Anonymous"))
.ForMember(d => d.FullName, opt => opt.MapFrom(s => s.FirstName + " " + s.LastName))
.ForMember(d => d.PostalCode, opt => opt.MapFrom(s => s.Address != null ? s.Address.PostalCode : null))
.ForMember(d => d.Age, opt => opt.Condition(s => s.Age.HasValue && s.Age.Value > 0))
.ForMember(d => d.AddressStreet, opt =>
{
opt.PreCondition(s => s.Address != null);
opt.MapFrom(s => s.Address.Street);
});
CreateMap<StudentDto, Student>()
.ForMember(d => d.Id, opt => opt.Ignore())
.ForMember(d => d.AddressId, opt => opt.Ignore())
.ForMember(d => d.UpdatedDate, opt => opt.MapFrom(s => DateTime.Now));
CreateMap<Address, AddressDto>();
CreateMap<AddressDto, Address>()
.ForMember(d => d.Id, opt => opt.Ignore());
}
}
Test:
// Create Entity
var entity = _mapper.Map<Student>(dto);
// Update Entity
_mapper.Map(dto, entity);
// Get Dto
var dto = _mapper.Map<StudentDto>(entity);
// Get Dto List
var dtoList = _mapper.Map<List<StudentDto>>(entityList);
标签:opt,set,string,映射,get,Add,AutoMapper,public
From: https://www.cnblogs.com/keirahuy/p/16816912.html