I don't think this is possible, but it's worth the question, I suppose.
I have the following types that share an interface (I promise, this isn't the same question I've asked before).
public interface ICustomer;
public class CustomerBO : ICustomer
public class CustomerSO : ICustomer // SO is Service Object in this case.
Then, I have the following mapping:
Mapper.Map<ICustomer, ICustomer>();
Now, here's where it gets interesting / confusing.
This works:
Mapper.Map<ICustomer, ICustomer>(customerSO, new CustomerBO);
This doesn't work:
Mapper.Map(customerSO, new CustomerBO());
Now, normally I wouldn't have a problem with just typing in the first Map statement with the two interface type defined, but my problem is when the Customer object is buried somewhere.
public class CustomerOrderDTO
{
ICustomer customer;
}
public class CustomerOrderSO
{
CustomerSO customer;
}
Mapper.Map<CustomerOrderDTO, CustomerOrderSO>();
This doesn't work, because there's no mapping from ICustomer to CustomerSO, so config assertion fails.
Currently, I'm going around the issue by doing this:
Mapper.CreateMap<CustomerOrderDTO, CustomerOrderSO>()
.ForMember(desc => dest.customer
, exp => exp.MapFrom(src => Mapper.Map<ICustomer, ICustomer>(src.customer
, new CustomerSO));
However, I would have to do this for every DTO-type object that we have, and then quite possibly have a cascading effect.
I understand that technically I could do the following to resolve the issue:
Mapper.Map<CustomerBO, CustomerSO>();
However, in CustomerBO there are a lot of other properties used in the business logic not in the interface. Similarly, there are a lot of properties in CustomerSO not in the interface. If I were to go with the above route, I would have a ton of Ignore() calls, and I'd have to map CustomerBO to CustomerSO, and then CustomerSO to CustomerBO, each with their own unique list of Ignore calls. Using the interfaces removes the need for the Ignore calls, as the data that I want to be visible from one to the other is defined in the interface.
So, in short, my question is this: is there some way I can tell AutoMapper to use the interface map when it encounters one of the implementing classes? Failing that, is there some other (read: better) way than a Map call in a MapFrom delegate to enforce my interface-to-interface mapping in a as-needed basis?
In general, you'd want to configure a mapping to the ICustomer
interface and override the destination type using .As<TDestination>()
. (Maybe this is an addition since you first asked the question.)
This would work for mappings between 2 layers, like your example:
Mapper.CreateMap<CustomerDTO, ICustomer>().As<CustomerModel>();
Mapper.CreateMap<CustomerModel, ICustomer>().As<CustomerDTO>();
However, extend this to another layer, such as mapping CustomerModel
to CustomerViewModel
, and this falls apart. You can only tell AutoMapper one destination type to use for instantiation.
But similar to the comments above, I would question the reason for having a property typed as the interface within those other classes. Why should a CustomerOrderModel
have a ICustomer customer
property? Can you replace customer with an instance of a CustomerDTO
and still have your program be correct? If you have common behavior for objects that contain a customer, you could have those parent objects implement an interface, ICustomerAccessor
. Then, use explicit interface implementation to add the weaker-typed property, and it won't have to interfere with the name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With