generics - Implementing .ToViewModel() using AutoMapper -


i'm trying ease use of automapper in project, implementing extension method .toviewmodel(). basically, wrapper around standard call, find myself annoyed how must type each time want map something. compare two:

var viewmodel = mapper.map<domainentitytype, viewmodeltype>(entity); // or... var viewmodel = entity.toviewmodel(); 

i feel number 2 sweet =) i've let entities extend ientity, , viewmodels (that correspond entity) extend iviewmodel<ientity>, , written following extension method:

public static iviewmodel<tentity> toviewmodel<tentity>(this tentity entity)      tentity : ientity {     return mapper.map<tentity, iviewmodel<tentity>>(entity); } 

however, i'm unable make fly.

the following nunit test makes attempt @ testing (although i'm unsure if assert.areequal tests want - require reference equality? if so, how test "are equivalent"?). test fails message

expected: <castle.proxies.iviewmodel`1proxy> 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 fact test might testing wrong thing, missing fundamental how automapper works? automapper ever able correctly map interface? (i have class, entityviewmodel, implements viewmodel<entity>, haven't told automapper it...)

i managed in generic way. required tweaking of objects, here's did:

since before, of entities inherit entity<tid> (usually entity<int>, id potentially data type, example guid), in turn implements interface ientity<tid> (with single property public tid id {get;}). few entities don't inherit entity<tid>, @ least implement ientity<tid>.

i created new class, overrides equals , gethashcode:

public class viewmodel<tentity, tid> : ientity<tid>     tentity : ientity<tid> {     public tid id { get; set; }      public override bool equals(object obj)     {         var viewmodel = obj viewmodel<tentity, tid>;         return viewmodel != null && equals(viewmodel);     }      public bool equals(viewmodel<tentity, tid> other)     {         return id.equals(other.id);     }      public override int gethashcode()     {         // not returning id.gethashcode() in case want add more         // properties later...         var hash = 7;         hash = (hash * 17) + id.gethashcode();          return hash;     } } 

now, viewmodels (and editmodels) inherit class:

public class entityviewmodel : viewmodel<entitytype, int> {     // data properties } 

i extend entities , viewmodels following extension methods:

public static tviewmodel to<tviewmodel>(this ientity entity) tviewmodel : class {     return mapper.map(entity, entity.gettype(), typeof(tviewmodel)) tviewmodel; }  public static tentity toentity<tentity, tid>(this viewmodel<tentity, tid> viewmodel) tentity : class, ientity<tid> {     return mapper.map(viewmodel, viewmodel.gettype(), typeof(tentity)) tentity; } 

a key concept make work abandon generic overloads of .map, since didn't know exact types wanted map , @ compile time.

i can move , forth between types using following syntax:

var entity = new entitytype(); var viewmodel = entity.to<entityviewmodel>();  var backagain = viewmodel.toentity(); 

which quite content with, since original goal of abstracting away automapper implementation in controllers have been achieved.

you'll notice there non-generic version of ientity - that's empty interface, ientity<t> inherits from. might considered dull, there's simple reason not use generic version: if do, you'll have specify type argument extension method. you'll end entity.to<entityviewmodel,int>() instead of above syntax, since inferring type arguments all-or-nothing affair.


Comments

Popular posts from this blog

c# - SharpSVN - How to get the previous revision? -

c++ - Is it possible to compile a VST on linux? -

url - Querystring manipulation of email Address in PHP -