How do I use AutoMapper to map multiple subclasses

2019-02-08 17:09发布

Let's assume I have three classes that are subclasses of a base class:

public class BaseClass
{
    public string BaseName { get; set; }
}

public class Subclass1 : BaseClass
{
    public string SubName1 { get; set; }
}

public class Subclass2 : BaseClass
{
    public string SubName2 { get; set; }
}

public class Subclass3 : BaseClass
{
    public string SubName3 { get; set; }
}

I would like to map these to a ViewModel class that looks like this:

public class ViewModel
{
    public string BaseName { get; set; }
    public string SubName1 { get; set; }
    public string SubName2 { get; set; }
    public string SubName3 { get; set; }
}

ViewModel simply combines the properties on all of the subclasses and flattens it. I tried to configure the mapping like so:

AutoMapper.CreateMap<BaseClass, ViewModel>();

Then I tried grabbing data from my database like so:

var items = Repo.GetAll<BaseClass>();
AutoMapper.Map(items, new List<ViewModel>());

However, what ends up happening is that only the BaseName property will be populated in the ViewModel. How would I configure AutoMapper so that it will map the properties in the subclasses as well?

2条回答
Root(大扎)
2楼-- · 2019-02-08 17:48

Try this:

AutoMapper.CreateMap<BaseClass, ViewModel>()
  .Include<Subclass1, ViewModel>()
  .Include<Subclass2, ViewModel>()
  .Include<Subclass3, ViewModel>();
AutoMapper.CreateMap<Subclass1, ViewModel>();
AutoMapper.CreateMap<Subclass2, ViewModel>();
AutoMapper.CreateMap<Subclass3, ViewModel>();

var items = Repo.GetAll<BaseClass>();
AutoMapper.Map(items, new List<ViewModel>());
查看更多
趁早两清
3楼-- · 2019-02-08 18:02

There appears to be a bug or limitation in AutoMapper that you need corresponding TSource and TDestination hierarchies. Given:

public class BaseClass {
    public string BaseName { get; set; }
}

public class Subclass1 : BaseClass {
    public string SubName1 { get; set; }
}

You need the following view models:

public class ViewModel {
    public string BaseName { get; set; }
}
public class ViewModel1 : ViewModel {
    public string SubName1 { get; set; }
}

The following code then works:

 Mapper.CreateMap<BaseClass, ViewModel>()
       .Include<Subclass1, ViewModel1>();
 Mapper.CreateMap<Subclass1, ViewModel1>();

 var items = new List<BaseClass> {new Subclass1 {BaseName = "Base", SubName1 = "Sub1"}};
 var viewModels = Mapper.Map(items, new List<ViewModel>());
查看更多
登录 后发表回答