Here is a simplified example of what I'm trying to do ... let's say I have the following interfaces:
public interface IPerson { int Id { get; set; } } public interface IModelPerson : IPerson { int BeautyCompetitionsWon { get; set; } }
In a real implementation, there are many different types of people (e.g., IUglyPerson , etc.). These are contracts for entity types, for example. in the following way:
public class PersonEntity : IPerson { public int Id { get; set; } } public class ModelPersonEntity : PersonEntity, IModelPerson { public int BeautyCompetitionsWon { get; set; } }
Note We can also have several implementations of each type of contract - for example, IModelPerson can also be implemented by SupermodelEntity .
We want to map our entity types to DTOs that look something like this:
public abstract class PersonDto : IPerson { public int Id { get; set; } public abstract string PersonType { get; } } public class ModelPersonDto : PersonDto, IModelPerson { public int BeautyCompetitionsWon { get; set; } public override string PersonType { get { return "Model"; } } }
Thus, we create a mapping:
Mapper.Initialize(config => { config.CreateMap<IPerson, PersonDto>() .Include<IModelPerson, ModelPersonDto>() .ConstructUsing((IPerson person) => { if (person is IModelPerson) return new ModelPersonDto(); throw new InvalidOperationException("Unknown person type: " + person.GetType().FullName); }) ; config.CreateMap<IModelPerson, ModelPersonDto>(); });
So, I have two questions.
1. Is there a way to create mappings without a ConstructUsing clause? I thought a more specific version of CreateMap took care of this for us, but if I don't have ConstructUsing , AutoMapper tells me: "Instances of abstract classes cannot be created."
2. Why properties from my subclasses are not displayed? If I perform the mapping as follows:
var source = new ModelPersonEntity { Id = 100, BeautyCompetitionsWon = 9 }; var target = Mapper.Map<PersonDto>(source);
The expected value for target.BeautyCompetitionsWon is 9, but the actual value is 0.