TL;DR:我在使用多态映射时遇到了问题。我制作了一个 github repo,其中包含一个说明我的问题的测试套件。请在此处找到它:链接到回购
我正在实现保存/加载功能。为此,我需要确保我正在序列化的域模型以序列化友好的方式表示。为此,我创建了一组 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 的代理,而不是将它们解析到域。
我怀疑问题出在我的映射配置文件上,但我的人才已经用完了。提前感谢您的意见。