I’m trying to ease the use of AutoMapper in my project, by implementing an extension method .ToViewModel(). Basically, it will just be a wrapper around the standard call, but I often find myself annoyed about how much I must type each time I want to map something. Compare the two:
var viewModel = Mapper.Map<DomainEntityType, ViewModelType>(entity);
// or...
var viewModel = entity.ToViewModel();
I feel number two would be sweet =) I’ve let all my entities extend IEntity, and all viewmodels (that correspond to an entity) extend IViewModel<IEntity>, and written the following extension method:
public static IViewModel<TEntity> ToViewModel<TEntity>(this TEntity entity)
where TEntity : IEntity
{
return Mapper.Map<TEntity, IViewModel<TEntity>>(entity);
}
However, I’m unable to make this fly.
The following NUnit test makes an attempt at testing this (although I’m unsure if Assert.AreEqual really tests what I want – does it require reference equality? If so, how do I test “are equivalent”?). The test fails with the message
Expected: <Castle.Proxies.IViewModel`1Proxy> But was: <Castle.Proxies.IViewModel`1Proxy>
[Test]
public void DomainEntityTypeMapsViewModelType()
{
var entity = new DomainEntityType();
var oldskool = Mapper.Map<DomainEntityType, IViewModel<Entity>>(entity);
var extension = inspectionObject.ToViewModel();
Assert.AreEqual(oldskool, extension);
}
Except for the fact that my test might be testing the wrong thing, am I missing something fundamental about how AutoMapper works? Will AutoMapper ever be able to correctly map something to an interface? (I do have a class, EntityViewModel, that implements ViewModel<Entity>, but I haven’t told AutoMapper specifically about it…)
I finally managed to do this in a generic way. It required some tweaking of my objects, but here’s what I did:
Since before, most of my entities inherit from
Entity<TId>(usuallyEntity<int>, but the id could potentially be another data type, for example a GUID), which in turn implements the interfaceIEntity<TId>(with a single propertypublic TId ID {get;}). The few entities that don’t inheritEntity<TId>, at least implementIEntity<TId>.I created a new class, which overrides
EqualsandGetHashcode:Now, all my viewmodels (and editmodels) inherit from this class:
I could then extend my entities and viewmodels with the following extension methods:
A key concept to make this work was to abandon the generic overloads of
.Map, since I didn’t know the exact types I wanted to map to and from at compile time.I can now move back and forth between the types using the following syntax:
which I am quite content with, since my original goal of abstracting away AutoMapper from the implementation in the controllers have been well achieved.
You’ll notice that there is a non-generic version of IEntity too – that’s just an empty interface, which
IEntity<T>inherits from. This might be considered dull, but there’s a simple reason not to use the generic version: if you do, you’ll also have to specify it as a type argument to the extension method. You’ll end up withentity.To<EntityViewModel,int>()instead of the above syntax, since inferring type arguments is an all-or-nothing affair.