TL; DR:我在多態映射方面遇到問題。我做了一個github回購測試套件,說明了我的問題。請在這裏找到它:LINK TO REPO使用AutoMapper的集合的多態映射
我正在實施保存/加載功能。爲了實現這一點,我需要確保序列化的域模型以序列化友好的方式表示。爲了達到這個目的,我創建了一套DTO,其中包含了執行有意義的保存或加載所需的最少量信息。
事情是這樣的域:
public interface IDomainType
{
int Prop0 { get; set; }
}
public class DomainType1 : IDomainType
{
public int Prop1 { get; set; }
public int Prop0 { get; set; }
}
public class DomainType2 : IDomainType
{
public int Prop2 { get; set; }
public int Prop0 { get; set; }
}
public class DomainCollection
{
public IEnumerable<IDomainType> Entries { get; set; }
}
...併爲DTO的
public interface IDto
{
int P0 { get; set; }
}
public class Dto1 : IDto
{
public int P1 { get; set; }
public int P0 { get; set; }
}
public class Dto2 : IDto
{
public int P2 { get; set; }
public int P0 { get; set; }
}
public class DtoCollection
{
private readonly IList<IDto> entries = new List<IDto>();
public IEnumerable<IDto> Entries => this.entries;
public void Add(IDto entry) { this.entries.Add(entry); }
}
的想法是,DomainCollection表示應用程序的當前狀態。我們的目標是將DomainCollection映射到DtoCollection的結果是一個DtoCollection的實例,它包含IDto在映射到域時的適當實現。反之亦然。
這裏有一點額外的技巧是不同的具體域類型來自不同的插件程序集,所以我需要找到一個優雅的方法來讓AutoMapper(或類似的,如果你知道更好的映射框架)做繁重的工作爲了我。
使用結構圖,我已經能夠找到並加載插件中的所有配置文件,並使用它們配置應用程序IMapper。
我試圖創建這樣的配置文件...
public class CollectionMappingProfile : Profile
{
public CollectionMappingProfile()
{
this.CreateMap<IDomainType, IDto>().ForMember(m => m.P0, a => a.MapFrom(x => x.Prop0)).ReverseMap();
this.CreateMap<DtoCollection, DomainCollection>().
ForMember(fc => fc.Entries, opt => opt.Ignore()).
AfterMap((tc, fc, ctx) => fc.Entries = tc.Entries.Select(e => ctx.Mapper.Map<IDomainType>(e)).ToArray());
this.CreateMap<DomainCollection, DtoCollection>().
AfterMap((fc, tc, ctx) =>
{
foreach (var t in fc.Entries.Select(e => ctx.Mapper.Map<IDto>(e))) tc.Add(t);
});
}
public class DomainProfile1 : Profile
{
public DomainProfile1()
{
this.CreateMap<DomainType1, Dto1>().ForMember(m => m.P1, a => a.MapFrom(x => x.Prop1))
.IncludeBase<IDomainType, IDto>().ReverseMap();
}
}
public class DomainProfile2 : Profile
{
public DomainProfile2()
{
this.CreateMap<DomainType2, IDto>().ConstructUsing(f => new Dto2()).As<Dto2>();
this.CreateMap<DomainType2, Dto2>().ForMember(m => m.P2, a => a.MapFrom(x => x.Prop2))
.IncludeBase<IDomainType, IDto>().ReverseMap();
}
}
我然後寫一個測試套件,以確保映射將像預期的那樣,當它的時間來此功能與應用程序整合。我發現每當DTO被映射到域(認爲加載)時,AutoMapper將創建IDomainType的代理,而不是將它們解析爲域。
我懷疑問題在於我的映射配置文件,但我已經用盡了人才。預先感謝您的意見。
Here's another link to the github repo