2016-02-12 9 views
8

Auf AutoMapper 4.2.0 aktualisiert und dem hier verfügbaren Migrationsleitfaden folgen: https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API/f4784dac61b91a0df130e252c91a0efd76ff51de#preserving-static-feel. Versuchen, Code auf dieser Seite für StructureMap zu Simple Injector zu übersetzen. Kann mir jemand zeigen, wie dieser Code in Simple Injector aussieht?Registrierung von AutoMapper 4.2.0 mit Simple Injector

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)); 
    } 
} 

Einfache Injector

? 

Antwort

10

Dies entspricht wäre:

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

Und Sie können die MapperConfigurationstion wahrscheinlich komplett entfernen, da es unwahrscheinlich ist, dass Ihre Komponenten davon abhängen. – Steven

+1

Registrierung der 'MapperConfiguration' ist nur sinnvoll, wenn Sie [LINQ-Projektionen] (https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API#linq-projections) verwenden. – mrmashal

+0

Wie sieht es mit mehreren MapperConfiguration (en) aus? Ich muss verschiedene Konfigurationen haben, Profile mischen, aber auf diese Weise kann ich nur einen IMapper registrieren. –

2

Einfache Injector IPackage Schnittstelle scheint, wie die nächste Äquivalent StructureMap des Registry-Typ. Hier ist das Paket, das ich verwende, den Aufbau von @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)); 
    } 
} 

Sie benötigen würden das SimpleInjector.Packaging Paket hinzufügen und dann einen Anruf zu container.RegisterPackages(); in der Bootstrap/Konfigurationscode hinzufügen.

Das einzige, was sich wirklich von StructureMap ändert, sind die letzten beiden Zeilen.

0

Für Mapping mehrere IMapper die mit verschiedenen MapperConfiguration Objekte, die eine etwas immer wieder auftretendes Problem scheint zu sein, empfehle ich die folgende Vorgehensweise, die nicht einmal braucht die Mapper-Methode aufruft Refactoring:

1) Erstellen einer generischen Wrapper um die IMapper-Schnittstelle. Dieser Wrapper kann entweder eine Schnittstelle oder eine Klasse sein, aber offensichtlich müssen Sie Ihren Wrapper implementieren, daher werde ich die konkrete Klasse unten zeigen. Lassen Sie sich diese Wrapper implementieren (oder erben, wenn Sie eine Schnittstelle machen wählte) die IMapper Schnittstelle, etwa so:

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(); 
    } 
} 

Das generische Argument muss eine Unterklasse von „Profil“ sein, denn von diesem Profil ist, wo Sie sind werde deine Mapper-Konfiguration bekommen.

2) In dieser Klasse implementieren die IMapper Schnittstelle einfach durch die Anrufe an die privaten IMapper Instanz umgeleitet, die Sie im Konstruktor, etwa so:

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

3) Nun müssen Sie in der Einfachen registrieren Injector eine teilweise geschlossene Instanz dieser ProfileMapper-Klasse für jedes Profil, das Sie haben. Sie tun dies zuerst, indem Sie alle Klassen erhalten, die von Profil erben, dann diese teilweise geschlossene Instanz erstellen und dann registrieren. Es gibt mehrere Wege, um alle Profilklassen, aber ich ging mit diesem:

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); 
    } 

Dieser Code zuerst alle Typen bekommt, die von Profil erben, befindet sich in dem Namespace. Dann registriere ich es für jedes Profil mit SimpleInjector (nicht wirklich notwendig, da es sich um konkrete Typen handelt und als solche vom Container im laufenden Betrieb erstellt werden kann), dann mache ich eine teilweise geschlossene Instanz meiner ProfileWrapper-Klasse mit der aktuellen Profil als generisches Argument, und schließlich registriere ich meine geschlossene Instanz als Singleton. Auf diese Weise können Sie neue Profile erstellen, ohne neue Wrapper manuell registrieren zu müssen.

Und das ist es.Statt nun je nach und Einspritzen des IMapper, injizieren Sie Ihre ProfileWrapper mit dem Profil, das Sie verwenden möchten, wie folgt aus:

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

und so weiter. Jeder Wrapper wurde mit einer separaten MapperConfiguration mit verschiedenen Profilen erstellt. Da der Wrapper den IMapper implementiert, bleibt der gesamte Mapping-Code gleich. Es ist nicht notwendig, die Methodenaufrufe zu refactorisieren, nur die Abhängigkeitstypen.

Wenn Sie ein BaseProfile erstellen, ändern Sie einfach den generischen Parameter in ProfileMapper, um nur Instanzen für dieses BaseProfile zu akzeptieren.