У меня возникла проблема с использованием AutoMapper (что является отличной технологией) для сопоставления бизнес-объекта с DTO, где у меня есть наследование от абстрактного базового класса в коллекции.
мои объекты:
abstract class Payment
class CashPayment : Payment
class CreditCardPayment : Payment
У меня также есть объект счета, который содержит коллекцию платежей, например:
public class Invoice
{
... properties...
public ICollection<Payment> Payments { get; set; }
}
У меня также есть соответствующие версии DTO каждого из этих объектов.
Объект DtoInvoice определяется как:
[DataContract]
public class DtoInvoice
{
...properties...
[DataMember]
public List<DtoPayment> Payments { get; set; }
}
Вот как выглядят мои определения Mapper:
Mapper.CreateMap<Invoice, DtoInvoice>();
Mapper.CreateMap<Payment, DtoPayment>()
.Include<CashPayment, DtoCashPayment>()
.Include<CreditCardPayment, DtoCreditCardPayment>();
Mapper.CreateMap<CashPayment, DtoCashPayment>();
Mapper.CreateMap<CreditCardPayment, DtoCreditCardPayment>();
Код для выполнения сопоставления выглядит следующим образом:
var invoice = repo.GetInvoice(invoiceId);
var dtoInvoice = Mapper.Map<Invoice, DtoInvoice>(invoice);
Так, например, если в моем объекте счета-фактуры содержится коллекция определенных платежей (например, 1 денежная единица и 1 кредитная карта) когда mapper пытается отобразить их, я получаю сообщение об ошибке, что абстрактный класс Payment не может быть создан. Если я удаляю абстрактное ключевое слово из объекта Payment, то код работает, но я получаю только коллекцию объектов Payment, я не получаю их конкретные объекты (платежи наличными и кредитной картой).
Поэтому возникает вопрос: как я могу заставить AutoMapper отображать конкретные типы платежей, а не базовый класс?
Обновление
Я провел еще несколько копаний и думаю, что вижу проблему, но не уверен, как решить эту проблему с AutoMapper. Я думаю, что это скорее вещь EF, а не вина AutoMapper. : -)
В моем коде я использую POCO-прокси Entity Framework 4 с отложенной загрузкой.
Поэтому, когда я пытаюсь отобразить сущность, возвращенную из EF, которая является POCO-прокси, она получает такой забавный вид, как:
System.Data.Entity.DynamicProxies.CashPayment_86783D165755C316A2F58A4343EEC4842907C5539AF24F0E64AEF498B15105C2
Итак, моя теория заключается в том, что когда AutoMapper пытается сопоставить CashPayment с DtoCashPayment, а переданный платеж имеет тип прокси, AutoMapper видит его как «не совпадающий», а затем сопоставляет общий тип Payment. Но поскольку Payment является абстрактным классом, бомбы AutoMapper имеют «System.InvalidOperationException: экземпляры абстрактных классов не могут быть созданы». исключение.
Поэтому возникает вопрос: есть ли способ использовать AutoMapper для сопоставления прокси-объектов EF POCO с Dtos.