Adding Inheritance to AutoMapper
Update: This is currently in the Automapper master, and will be included in the v2 release (hopefully Before/After map will also get included, patch submitted).
In my current project, we are leveraging AutoMapper a lot to map our Domain to Dto's. The major problem we are facing is that our mappings are getting quite complex and bloated, especially for flattened Dtos or Summaries which have properties that cover all the properties from the concrete types they come from. It seemed unnatural that I could define a mapping that looked like:
Mapper.CreateMap<ItemBase, ItemSummaryDto>()
.ForMember(d => d.Description, m => m.MapFrom(s => s.ItemSummary))
.Include<GeneralItem, GeneralItemSummaryDto>()
.Include<SpecificItem, SpecificItemSummaryDto>();
Mapper.CreateMap<GeneralItem, GeneralItemSumaryDto>()
.ForMember(d => d.GeneralProperty, m => m.MapFrom(s => s.Something));
Mapper.CreateMap<SpecificItem, SpecificItemSumaryDto>()
.ForMember(d => d.SpecificProperty, m => m.MapFrom(s => s.Something));
And have the rest of the properties map by convention. The problem is that the .Include function is only used for type resolution. i.e.
var dto = Mapper.Map
If we validate our mapping we will find that Description is not mapped on GeneralItemSummaryDto and SpecificItemSummaryDto. This means out mapping ends up being:
Mapper.CreateMap<ItemBase, ItemSummaryDto>()
.Include<GeneralItem, GeneralItemSummaryDto>()
.Include<SpecificItem, SpecificItemSummaryDto>();
Mapper.CreateMap<GeneralItem, GeneralItemSumaryDto>()
.ForMember(d => d.Description, m => m.MapFrom(s => s.ItemSummary))
.ForMember(d => d.GeneralProperty, m => m.MapFrom(s => s.Something));
Mapper.CreateMap<SpecificItem, SpecificItemSumaryDto>()
.ForMember(d => d.Description, m => m.MapFrom(s => s.ItemSummary))
.ForMember(d => d.SpecificProperty, m => m.MapFrom(s => s.Something));
We have to duplicate the mapping of the Description property on both the items. For my current project this means our mappings are far more complicated than they need to be, and have massive amounts of duplicated ForMember(d=>d.Blah, m=>m.Ignore()) mappings because we have many flattened summary dtos which have properties from many of the concrete types that are mapped.
Unfortunately it ended up being quite a difficult task, and with our complex mappings my initial implementations resulted in a few issues. I am pretty sure I have got most of them and have created quite a few unit tests covering it. Especially with collections of a base type, holding different concrete types.
Is anyone interested in this functionality? If so let me know and I will create a proper Fork on Github and share my changes. I still need to cleanup the unit tests and the code a little bit as the AutoMapper codebase is really nice and I don't want to make it messy.
Comments
Dave
Interesting work, would be very interested in seeing the code! May very well help in my current project too.
Jeroen de Bekker
Hi Jake,
I am interested as well.
This is just what we need; we also stumbled upon the fact that Automapper does not support inheritance of the mapping configuration. Before doing it myself, I searched the internet for a brave soul who might already did this, and I found you. Good job! :-).
Kind regards, Jeroen
lewis p webb
I must agree with the rest of the camp; can't believe the first comment to this post was only weeks ago. I am very interested in seeing your code and the unit tests that you have built that verifies the inheritance automapping functionality. MANY THANKS!
Jake Ginnivan
Hey guys,
I am on this, I have to pull the code out as it was a while ago I wrote it, and the automapper master has likely moved on a fair bit.
I will try to dig up both my changes to master, and the current 1.1 release and post it onto the Automapper mailing list, and here as well.
Jeroen de Bekker
For anyone interested: I discovered that Jake's inheritance implementation is already integrated in the Automapper's repository on GitHub: https://github.com/automapper/automapper. If you look to the commits you can see it has been merged from the 1.1 to the master on 2010-11-11. It's also present in the 3.5 branch if you're using .NET 3.5.
If you're fine with fetching a non-official release, you can get and use the most recent revision for now.
John
Hi Jake,
I'm very surprised to be the first person to comment on this post. Inheritance is a key piece of functionality I feel AutoMapper needs and something that will help reduce many lines of duplicated mappings. For what it is worth, I would be very pleased to see this added to AutoMapper and would be interested in your implementation.
Regards John