« Automapper » : différence entre les versions
De Banane Atomic
Aller à la navigationAller à la recherche
Ligne 155 : | Ligne 155 : | ||
var a = new A { P1 = 1 }; | var a = new A { P1 = 1 }; | ||
var b = mapper.Map<B>(a, opt => opt.Items["+"] = 9); | var b = mapper.Map<B>(a, opt => opt.Items["+"] = 9); | ||
</kode> | |||
== Map 1 object to multiple objects == | |||
<kode lang='cs'> | |||
var config = new MapperConfiguration(cfg => | |||
{ | |||
cfg.CreateMap<D, FlatD>(); | |||
cfg.CreateMap<int, FlatD>() | |||
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src)); | |||
cfg.CreateMap<D, IEnumerable<FlatD>>() | |||
.ConvertUsing<DToFlatDConverter>(); | |||
}); | |||
IMapper mapper = config.CreateMapper(); | |||
var d = new D | |||
{ | |||
Name = "D", | |||
Ids = { 1, 2, 3 } | |||
}; | |||
var flatDs = mapper.Map<IEnumerable<FlatD>>(d).ToList(); | |||
class DToFlatDConverter : ITypeConverter<D, IEnumerable<FlatD>> | |||
{ | |||
public IEnumerable<FlatD> Convert( | |||
D source, | |||
IEnumerable<FlatD> destination, | |||
ResolutionContext context) | |||
{ | |||
foreach (var id in source.Ids) | |||
{ | |||
var flatD = context.Mapper.Map<FlatD>(id); | |||
context.Mapper.Map(source, flatD); | |||
yield return flatD; | |||
} | |||
} | |||
} | |||
class D | |||
{ | |||
public string Name { get; set; } | |||
public ICollection<int> Ids { get; } = new List<int>(); | |||
} | |||
class FlatD | |||
{ | |||
public string Name { get; set; } | |||
public int Id { get; set; } | |||
} | |||
</kode> | </kode> | ||
Version du 22 avril 2020 à 18:21
Description
Permet le mapping d'un objet de type A vers un objet de type B.
AutoMapper utilise des convention de mapping afin de réduire le paramétrage:
- Propriétés de même nom
- Flattening
- Ignore les références null
Liens
- Getting Started
- Static and Instance API
- AutoMapper.Collection bibliothèque externe pour géré les collections
- Map 1 object to list of objects
Setup and configuration
var config = new MapperConfiguration(cfg => { // configure mapping from Source to Dest cfg.CreateMap<Source, Dest>(); // load the configuration from AppProfile cfg.AddProfile<AppProfile>(); // load the configuration from all classes who inherits from Profile in the current assembly cfg.AddProfiles(typeof(ContainerConfig).Assembly); }); IMapper mapper = config.CreateMapper(); IMapper mapper = new Mapper(config); |
Profile
AProfile.cs |
internal sealed class AProfile : Profile { public AProfile() { this.CreateAToBMapping(); this.CreateBToAMapping(); } private void CreateAToBMapping() { this.CreateMap<A, B>() .ForMember(dest => dest.B1, opt => opt.MapFrom(src => src.A1)); } private void CreateBToAMapping() { this.CreateMap<B, A>() .ForMember(dest => dest.A1, opt => opt.MapFrom(src => src.B1));; } } |
Dependency Injection
Add the nuget package AutoMapper.Extensions.Microsoft.DependencyInjection |
Startup.cs |
public void ConfigureServices(IServiceCollection services) { // add as parameter one type for each assembly services.AddAutoMapper(typeof(ProfileTypeFromAssembly1), typeof(ProfileTypeFromAssembly2)); |
Exemple
var config = new MapperConfiguration(cfg => { cfg.CreateMap<A, B>() .ForMember(dst => dst.Q2, opts => opts.MapFrom(src => src.P2)); // map A.P2 → B.Q2 .ReverseMap(); // map B → A }); IMapper mapper = config.CreateMapper(); C c = new C() { P1 = 3 }; A a = new A() { P1 = 1, C1 = c }; B b = mapper.Map<B>(a); // b.P1 = 1, b.Q2 = 2, b.C1P1 = 3 class A { public int P1 { get; set; } public int P2 { get; set; } public C C1 { get; set; } } class B { public int P1 { get; set; } // mapping par convention avec A.P1 public int Q2 { get; set; } // mapping par configuration avec A.P2 public int C1P1 { get; set; } // mapping par flattening avec A.C1.P1 } class C { public int P1 { get; set; } } |
If the mapping has not been configured, you will get an AutoMapper.AutoMapperMappingException |
List and polymorphism
// avec une liste List<B> listB = Mapper.Map<List<A>, List<B>>(listA); // polymorphism cfg.CreateMap<Parent1, Parent2>() .Include<Child1, Child2>(); // IncludeAllDerived(); to include all the derived classes // without the include, the resulting list contains only Parent2 objects (no Child2 objects) cfg.CreateMap<Child1, Child2>(); var lp1 = new List<Parent1> { new Parent1 { P1 = 1}, new Child1 { P1 = 2, P2 = 22 } }; var lp2 = mapper.Map<List<Parent2>>(lp1); // Parent2, Child2 class Parent1 { public int P1 { get; set; } } class Child1 : Parent1 { public int P2 { get; set; } } class Parent2 { public int P1 { get; set; } } class Child2 : Parent2 { public int P2 { get; set; } } |
Pass parameter to the mapping
var config = new MapperConfiguration(cfg => { cfg.CreateMap<A, B>() .ForMember(dest => dest.P1, opt => opt.MapFrom((src, dest, destMember, resContext) => src.P1 + (int)resContext.Items["+"])); }); IMapper mapper = config.CreateMapper(); var a = new A { P1 = 1 }; var b = mapper.Map<B>(a, opt => opt.Items["+"] = 9); |
Map 1 object to multiple objects
var config = new MapperConfiguration(cfg => { cfg.CreateMap<D, FlatD>(); cfg.CreateMap<int, FlatD>() .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src)); cfg.CreateMap<D, IEnumerable<FlatD>>() .ConvertUsing<DToFlatDConverter>(); }); IMapper mapper = config.CreateMapper(); var d = new D { Name = "D", Ids = { 1, 2, 3 } }; var flatDs = mapper.Map<IEnumerable<FlatD>>(d).ToList(); class DToFlatDConverter : ITypeConverter<D, IEnumerable<FlatD>> { public IEnumerable<FlatD> Convert( D source, IEnumerable<FlatD> destination, ResolutionContext context) { foreach (var id in source.Ids) { var flatD = context.Mapper.Map<FlatD>(id); context.Mapper.Map(source, flatD); yield return flatD; } } } class D { public string Name { get; set; } public ICollection<int> Ids { get; } = new List<int>(); } class FlatD { public string Name { get; set; } public int Id { get; set; } } |
MOQ
var mapperMock = new Mock<IMapper>(); mapperMock.Setup(x => x.Map<ItemDto>(It.IsAny<Item>())) .Returns(new ItemDto()); |
Installation
NuGet → AutoMapper
ASP.NET Core
NuGet → AutoMapper.Extensions.Microsoft.DependencyInjection
Startup.cs |
public void ConfigureServices(IServiceCollection services) { services.AddAutoMapper(); |
MyController.cs |
private readonly IMapper _mapper; public MyController(IMapper mapper) { _mapper = mapper; B b = _mapper.Map<A, B>(a); |
Configuration dans Profile