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; }
}
... и для DTOS
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();
}
}
Я тогда написал набор тестов, чтобы убедиться, что отображение будет вести себя, как ожидается, когда его время, чтобы интегрировать эту функцию с приложением , Я обнаружил, что когда DTOs сопоставлялись с Domain (think Load), AutoMapper создавал бы прокси из IDomainType вместо того, чтобы разрешать их в домене.
Я подозреваю, что проблема связана с моими профилями профиля, но у меня закончились таланты. Спасибо заранее за ваш вклад.
Here's another link to the github repo