I am having an issue using AutoMapper (which is an excellent technology) to map a business object to a DTO where I have inheritance off of an abstract base class within a collection.
Here are my objects:
abstract class Payment
class CashPayment : Payment
class CreditCardPayment : Payment
I also have an invoice object which contains a collection of payments like so:
public class Invoice
{
... properties...
public ICollection<Payment> Payments { get; set; }
}
I also have corresponding DTO versions of each of these objects.
The DtoInvoice object is defined as:
[DataContract]
public class DtoInvoice
{
...properties...
[DataMember]
public List<DtoPayment> Payments { get; set; }
}
This is what my Mapper definitions look like:
Mapper.CreateMap<Invoice, DtoInvoice>();
Mapper.CreateMap<Payment, DtoPayment>()
.Include<CashPayment, DtoCashPayment>()
.Include<CreditCardPayment, DtoCreditCardPayment>();
Mapper.CreateMap<CashPayment, DtoCashPayment>();
Mapper.CreateMap<CreditCardPayment, DtoCreditCardPayment>();
The code to perform the mapping looks like this:
var invoice = repo.GetInvoice(invoiceId);
var dtoInvoice = Mapper.Map<Invoice, DtoInvoice>(invoice);
So for example if my invoice object contains a collection of specific payments (say 1 cash and 1 credit card) when mapper tries to map them I get an error that the abstract class Payment cannot be created. If I remove the abstract keyword from the Payment object then the code works but I only get a collection of Payment object, I do not get their specific objects (Cash & Credit Card payments).
So the question is: How can I get AutoMapper to map the specific payment types and not the base class?
Update
I did some more digging and think I see a problem but am not sure how I can solve this with AutoMapper. I think this is more of an EF thing and not AutoMapper's fault. :-)
In my code I am using Entity Framework 4 Proxy POCOs with lazy loading.
So when I try to map an entity returned from EF that is a proxy POCO it gets that funny looking type like:
System.Data.Entity.DynamicProxies.CashPayment_86783D165755C316A2F58A4343EEC4842907C5539AF24F0E64AEF498B15105C2
So my theory is that when AutoMapper tries to map CashPayment to DtoCashPayment and the payment passed in is of the proxy type AutoMapper sees it as a "non match" and then maps the generic Payment type. But since Payment is an abstract class AutoMapper bombs with a "System.InvalidOperationException: Instances of abstract classes cannot be created." exception.
So the question is: Is there a way for me to use AutoMapper to map EF POCO proxy objects to Dtos.
I ran into the same issue with Entity Framework proxies, but didn't want to switch to a pre-release version of AutoMapper. I found a simple if slightly ugly work around for version 2.2.0. I was trying to go from a DTO to an existing EF proxy object, and was getting errors about missing a mapping for the ugly proxy class name. My solution was to use an overload the specified the actual concrete types that I'd manually mapped:
This answer comes 'a bit' late as I've just faced the same issue with EF4 POCO proxies.
I solved it using a custom converter that calls
Mapper.DynamicMap<TDestination>(object source)
to invoke the runtime type conversion, rather than the.Include<TOtherSource, TOtherDestinatio>()
.It works fine for me.
In your case you would define the following converter:
And then:
I also tried Olivier's example and got the same StackOverflow errors. I also tried subkamran's solution but not luck there as I am not using a base class from the entity model code generation. Automapper still blows up. Until I find a better solution, I just set the Context to not create Proxies when I create a Context object.
I would also like to see an answer to the problem perhaps using something build into Automapper...
UPDATE: The Pre-release of Automapper corrects this issue and allows for the mapping to cover a DynamicProxy with no extra configuration.
The release this works in is 2.2.1
I've just faced the same problem with mapping dynamic EF proxies to ViewModels in MVC application.
I found an easy solution using Mapper.DynamicMap() for this problem. Here is my code:
Converting from Dynamic proxy to ViewModel class:
Converting from ViewModel class to EF Dynamic Proxy:
Hope this example help you
Building on Olivier's response, I could not get his to work in my context... it kept going in an infinite loop and threw a StackOverflowException.
In this example,
AbstractClass
is my base class andAbstractViewModel
is my base view model (not marked asabstract
mind you).However, I did get it to work using this hackish looking converter:
So, a
DerivedClassA
will map normally, but aDynamicProxy_xxx
will also map properly as this code inspects its base type (DerivedClassA
).Please, please, please show me that I don't have to do this crazy lookup crap. I don't know enough AutoMapper to fix Olivier's answer properly.