2

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?

Luca
  • 75
  • 7
  • 1
    You mean because of polymorphism? So you have a single list with `People` in, and some of the list might be `Manager` and some might be `Employee`? If that's the case, it would make sense that applying one of your `Profile` would cause an exception because it'll be trying to map to either `Manager` or `Employee` when the list contains both types... Having said this, I thought Automapper would just not map props that don't exist on the Dest rather than throwing an exception. Maybe the question is missing some information (i.e. what is the Exception message?) – Thomas Cook Jul 10 '17 at 08:28
  • I edited the question with more information. Exception thrown is misleading because it seems that the mapper is not able to map a field but internally there is an object reference not set because probably automapper tries to create an instance of "Person" but as it's abstract it can't. – Luca Jul 10 '17 at 08:42
  • Look at: https://github.com/AutoMapper/AutoMapper/wiki/Mapping-inheritance and https://stackoverflow.com/questions/39884805/polymorphic-mapping-of-collections-with-automapper – Thomas Cook Jul 10 '17 at 08:51

1 Answers1

1

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>();
Richard
  • 29,854
  • 11
  • 77
  • 120
  • Thanks for you answer. After the double mapping declaration if I try to check the configuration with `cm.AssertConfigurationIsValid();` I get an error caused by the double configuration but the text of the error message contains a suggestion of using `AllowAdditiveTypeMapCreation`. If i set to true that property before the double mapping the assertion doesn't fire any exception, but the mapping is still not working. However I tried to declare the mapping in your way and seems working fine. Thank you – Luca Jul 10 '17 at 10:37