2016-02-12 19 views
8

Zaktualizowano do wersji AutoMapper 4.2.0 i postępując zgodnie z podręcznikiem migracji dostępnym tutaj: https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API/f4784dac61b91a0df130e252c91a0efd76ff51de#preserving-static-feel. Próbuję przetłumaczyć kod na tej stronie dla StructureMap na Simple Injector. Czy ktoś może mi pokazać, jak wygląda ten kod w Simple Injector?Jak zarejestrować AutoMapper 4.2.0 z prostym wtryskiwaczem

StructureMap

public class AutoMapperRegistry : Registry 
{ 
    public AutoMapperRegistry() 
    { 
     var profiles = 
      from t in typeof (AutoMapperRegistry).Assembly.GetTypes() 
      where typeof (Profile).IsAssignableFrom(t) 
      select (Profile)Activator.CreateInstance(t); 

     var config = new MapperConfiguration(cfg => 
     { 
      foreach (var profile in profiles) 
      { 
       cfg.AddProfile(profile); 
      } 
     }); 

     For<MapperConfiguration>().Use(config); 
     For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance)); 
    } 
} 

Proste Injector

? 

Odpowiedz

10

Byłoby to równoważne: Interfejs IPackage

container.RegisterSingleton<MapperConfiguration>(config); 
container.Register<IMapper>(() => config.CreateMapper(container.GetInstance)); 
+0

Prawdopodobnie można całkowicie usunąć "MapperConfigurstation", ponieważ jest mało prawdopodobne, aby od niego zależały. – Steven

+1

rejestracja 'MapperConfiguration' jest użyteczna tylko przy użyciu [projekcji LINQ] (https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API#linq-projections). – mrmashal

+0

co z wieloma MapperConfiguration (s)? Muszę mieć różne konfiguracje, mieszanie profili, ale w ten sposób mogę zarejestrować tylko jednego IMappera. –

2

prosty wtryskiwacz wydaje jak najbliższego odpowiednika StructureMap typ rejestru. Oto pakiet używam, budynek z @Steven's answer:

using System; 
using System.Linq; 
using System.Reflection; 
// 
using AutoMapper; 
// 
using SimpleInjector; 
using SimpleInjector.Packaging; 

public class AutoMapperPackage : IPackage 
{ 
    public void RegisterServices(Container container) 
    { 
     var profiles = Assembly.GetExecutingAssembly() 
      .GetTypes() 
      .Where(x => typeof(AutoMapper.Profile).IsAssignableFrom(x)); 

     var config = new MapperConfiguration(cfg => 
     { 
      foreach (var profile in profiles) 
      { 
       cfg.AddProfile(Activator.CreateInstance(profile) as AutoMapper.Profile); 
      } 
     }); 

     container.RegisterSingleton<MapperConfiguration>(config); 
     container.Register<IMapper>(() => config.CreateMapper(container.GetInstance)); 
    } 
} 

Trzeba by dodać pakiet SimpleInjector.Packaging, a następnie dodać wywołanie do container.RegisterPackages(); w kodzie bootstrap/konfiguracji.

Zasadniczo jedyną rzeczą, która naprawdę zmienia się z StructureMap, byłyby dwie ostatnie linie.

0

do mapowania wielu IMapper jest z różnych obiektów MapperConfiguration, które wydaje się być nieco powtarzający się problem, polecam następujące podejście, które nawet nie potrzeba refactoring sposób odwzorowujący wzywa:

1) Utwórz rodzajowe otoki wokół interfejsu IMapper. To opakowanie może być interfejsem lub klasą, ale oczywiście ostatecznie musisz zaimplementować swoje opakowanie, więc pokażę konkretną klasę poniżej. Mają to wrapper realizować (lub dziedziczenia, jeśli zdecydowaliśmy się dokonać Interface) interfejs IMapper, tak:

public class ProfileMapper<TProfile> : IMapper where TProfile : Profile 
{ 
    private IMapper mapper; 
    private Profile profile; 

    public ProfileMapper(TProfile profile) 
    { 
     this.profile = profile; 
     this.mapper = new MapperConfiguration(cfg => cfg.AddProfile(this.profile)) 
        .CreateMapper(); 
    } 
} 

Ogólny argument musi być podklasą „Profil”, bo z tego profilu, gdzie jesteś zdobędę konfigurację mappera.

2) W tej klasie, implementować interfejs IMapper prostu poprzez przekierowanie połączenia do prywatnej przykład IMapper że utworzone w konstruktorze tak:

public TDestination Map<TDestination>(object source) 
{ 
    return mapper.Map<TDestination>(source); 
} 

3) Teraz trzeba zarejestrować w prosty Injector to częściowo zamknięte wystąpienie tej klasy ProfileMapper dla każdego posiadanego profilu. Robisz to najpierw, uzyskując wszystkie klasy, które dziedziczą z profilu, a następnie tworząc tę ​​częściowo zamkniętą instancję, a następnie rejestrując ją. Istnieje kilka sposobów na uzyskanie wszystkich klas profilu, ale poszedłem z tym:

IEnumerable<Type> profileRegistrations = 
       from type in profileAssembly.GetExportedTypes() 
       where type.Namespace == "Namespace.Of.My.Profiles" 
       where type.BaseType.Equals(typeof(Profile)) 
       select type; 

    foreach (Type profileType in profileRegistrations) 
    { 
     Container.RegisterSingleton(profileType, profileType); 
     Type mapperClosedType = typeof(ProfileMapper<>).MakeGenericType(profileType); 
     Container.RegisterSingleton(typeof(ProfileMapper<>), mapperClosedType); 
    } 

Kod ten pierwszy dostaje wszystkich typów, które dziedziczą z profilu, usytuowany we wspomnianej przestrzeni nazw. Następnie dla każdego profilu rejestruję go za pomocą SimpleInjector (niekoniecznie, ponieważ są to konkretne typy i jako takie mogą być tworzone przez kontener w locie), a następnie wykonuję częściowo zamknięte wystąpienie mojej klasy ProfileWrapper z bieżącym Profil jako ogólny argument, a następnie rejestruję moją zamkniętą instancję jako Singleton. W ten sposób możesz tworzyć nowe Profile bez konieczności ręcznego rejestrowania nowych Owijaczy.

I to wszystko.Teraz, zamiast zależności i wstrzykiwanie IMapper, należy wstrzykiwać ProfileWrapper z profilem, który chcesz użyć, na przykład:

ProfileMapper<ApplicationProfile> appProfileMapper; 
ProfileMapper<MvcProfile> mvcProfileMapper; 
ProfileMapper<GuestProfile> guestProfile; 

i tak dalej. Każdy Wrapper został stworzony przy użyciu oddzielnej MapperConfiguration przy użyciu różnych profili. Ponieważ opakowanie obsługuje aplikację IMapper, cały kod odwzorowania pozostaje taki sam. Nie ma potrzeby refaktoryzacji wywołań metod, tylko typy zależności.

Jeśli tworzysz program BaseProfile, po prostu zmień parametr ogólny w narzędziu ProfileMapper, aby akceptował tylko instancje tego BaseProfile.