Search code examples
subclassautomappersuperclass

Use Automapper to flatten sub-class of property


Given the classes:

public class Person
{
    public string Name { get; set; }
}

public class Student : Person
{
    public int StudentId { get; set; }
}

public class Source
{
    public Person Person { get; set; }
}

public class Dest
{
    public string PersonName { get; set; }
    public int? PersonStudentId { get; set; }
}

I want to use Automapper to map Source -> Dest.

This test obviously fails:

Mapper.CreateMap<Source, Dest>();
var source = new Source() { Person = new Student(){ Name = "J", StudentId = 5 }};

var dest = Mapper.Map<Source, Dest>(source);
Assert.AreEqual(5, dest.PersonStudentId);

What would be the best approach to mapping this given that "Person" is actually a heavily used data-type throughout our domain model.

Edit: The intent is to persist the "Dest" objects which will have fields defined for all properties of the sub-types of "Person". Hence we could have source objects like the following and would prefer not to have to create Dest objects for every possible combination of "Person" sub-classes:

public class Source2
{
    public Person Value1 { get; set; }
    public Person Value2 { get; set; }
    public Person Value3 { get; set; }
    public Person Value4 { get; set; }
    public Person Value5 { get; set; }
}

Solution

  • Well using Jimmy's suggestion I've settled on the following solution:

    public class Person
    {
        public string Name { get; set; }
    }
    
    public class Student : Person
    {
        public int StudentId { get; set; }
    }
    //all subtypes of person will map to this dto
    public class PersonDto
    {
        public string Name { get; set; }
        public int? StudentId { get; set; }
    }
    
    public class Source
    {
        public Person Person { get; set; }
    }
    
    public class DestDto
    {
        public PersonDto Person { get; set; }
    }
    
    public class Dest
    {
        public string PersonName { get; set; }
        public int? PersonStudentId { get; set; }
    }
    
    [TestFixture]
    public class RandomTests
    {
        [Test]
        public void Test1()
        {
            Mapper.CreateMap<Person, PersonDto>();
            Mapper.CreateMap<Student, PersonDto>();
    
            Mapper.CreateMap<Source, DestDto>();
            Mapper.CreateMap<DestDto, Dest>();
    
            var source = new Source() { Person = new Student() { Name = "J", StudentId = 5 } };
    
            var destDto = Mapper.Map<Source, DestDto>(source);
            var destFinal = Mapper.Map<DestDto, Dest>(destDto);
    
            Assert.AreEqual(5, destFinal.PersonStudentId);
        }
    }
    

    Would love to hear suggestions/improvements.