I need to implement a pluggable system where Automapper profiles can be provided by many DLL.
The object to be mapped has a list of persons:
public class CompanySrc
{
public List<PersonSrc> Persons {get;set;}
}
public class CompanyDest
{
public List<PersonDest> Persons {get;set;}
}
PersonSrc and PersonDest are abstract classes that can be extended in each DLL:
DLL1:
public class EmployeeSrc : PersonSrc
{
...
}
public class EmployeeDest : PersonDest
{
...
}
DLL2:
public class ManagerSrc : PersonSrc
{
...
}
public class ManagerDest : PersonDest
{
...
}
The idea was to implement something similar to this:
public class DLL1Profile : Profile
{
public DLL1Profile()
{
CreateMap<PersonSrc, PersonDest>()
.Include<EmployeeSrc, EmployeeDest>();
CreateMap<EmployeeSrc, EmployeeDest>();
}
}
public class DLL2Profile : Profile
{
public DLL2Profile()
{
CreateMap<PersonSrc, PersonDest>()
.Include<ManagerSrc, ManagerDest>();
CreateMap<ManagerSrc, ManagerDest>();
}
}
Mapping is done in the following way
var mc = new MapperConfiguration(cfg =>
{
cfg.CreateMap<CompanySrc, CompanyDest>()
cfg.AddProfile(new DLL1Profile());
cfg.AddProfile(new DLL2Profile ());
});
IMapper sut = mc.CreateMapper();
var result = sut.Map<CompanyDest>(companySrc);
but this approach is not working. When the "People" list contains an Employee and a Manager, and I try to map the whole list I get an exception. Any suggestion?
You are seeing this problem because you have multiple calls to CreateMap<PersonSrc, PersonDest>()
- only one mapping can exist.
When you are extending your base class in different DLLs, don't use .Include
, use .IncludeBase
instead. Include requires that the profile including your base class is able to reference the derived class, which is most likely not what you want to happen.
You should define your base mapping somewhere common, presumably where Person is defined:
CreateMap<PersonSrc, PersonDest>();
In your DLL1 profile etc, use IncludeBase
instead:
CreateMap<ManagerSrc, ManagerDest>()
.IncludeBase<PersonSrc, PersonDest>();