Can I use inheritance mapping in AutoMapper (v2.2) for maps with the same Source type but different Destination types?
I have this basic situation (the real classes have many more properties):
public abstract class BaseViewModel
{
public int CommonProperty { get; set;}
}
public class ViewModelA : BaseViewModel
{
public int PropertyA { get; set; }
}
public class ViewModelB : BaseViewModel
{
public int PropertyB { get; set; }
}
ViewModelA
and ViewModelB
are different representations of the same Entity class:
public class Entity
{
public int Property1 { get; set; }
public int Property2 { get; set; }
public int Property3 { get; set; }
}
I want to reuse the same mapping for BaseViewModel
for each ViewModel, such as:
Mapper.CreateMap<Entity, BaseViewModel>()
.Include<Entity, ViewModelA>()
.Include<Entity, ViewModelB>()
.ForMember(x => x.CommonProperty, y => y.MapFrom(z => z.Property1));
Mapper.CreateMap<Entity, ViewModelA>()
.ForMember(x => x.PropertyA, y => y.MapFrom(z => z.Property2));
Mapper.CreateMap<Entity, ViewModelB>()
.ForMember(x => x.PropertyB, y => y.MapFrom(z => z.Property3));
But unfortunately, this doesn't seem to work. Calls like these:
var model = Mapper.Map<Entity, ViewModelA>(entity);
result in model
having PropertyA
mapped, but not CommonProperty
. I believe I'm following the examples in https://github.com/AutoMapper/AutoMapper/wiki/Mapping-inheritance properly, but I'm afraid having multiple maps created with the same Source type is tripping AutoMapper up.
Any insights? I love the idea of grouping Base class mappings together, but this doesn't seem to work.
Unfortunately in this case, AutoMapper seems to be registering only one child class mapping per source type, the last one (ViewModelB
). This was probably designed to work with parallel hierarchies, not with a single source type.
To work around this, you can encapsulate the common mappings in an extension method:
public static IMappingExpression<Entity, TDestination> MapBaseViewModel<TDestination>(this IMappingExpression<Entity, TDestination> map)
where TDestination : BaseViewModel {
return map.ForMember(x => x.CommonProperty, y => y.MapFrom(z => z.Property1));
}
And use it in the individual subclass mappings:
Mapper.CreateMap<Entity, ViewModelA>()
.MapBaseViewModel<ViewModelA>()
.ForMember(x => x.PropertyA, y => y.MapFrom(z => z.Property2));
Mapper.CreateMap<Entity, ViewModelB>()
.MapBaseViewModel<ViewModelB>()
.ForMember(x => x.PropertyB, y => y.MapFrom(z => z.Property3));