2012-09-26 14 views
14

Die meisten Beispiele, die ich für Automapper gefunden habe, verwenden das statische Mapper-Objekt für die Verwaltung von Typzuordnungen. Für mein Projekt muss ich eine IMapperEngine als Teil der Objektkonstruktion mithilfe von StructureMap einfügen, damit wir den Mapper in Komponententests überspionieren können, sodass wir den statischen Mapper nicht verwenden können. Ich muss auch die Konfiguration von AutoMapper-Profilen unterstützen.So injizieren Sie AutoMapper IMappingEngine mit StructureMap

Meine Frage ist, wie kann ich die StructureMap Registrierung so konfigurieren, dass es eine Instanz von IMappingEngine liefern kann, wenn eine Instanz von MyService erstellt wird. Hier

ist der Service-Konstruktor Unterschrift:

public MyService(IMappingEngine mapper, IMyRepository myRepository, ILogger logger) 

Und hier ist die StructureMap Registry

public class MyRegistry : StructureMap.Configuration.DSL.Registry 
{ 
    public MyRegistry() 
    { 
     For<IMyRepository>().Use<MyRepository>(); 
     For<ILogger>().Use<Logger>(); 
     //what to do for IMappingEngine? 
    } 
} 

und das Profil I

public class MyAutoMapperProfile : AutoMapper.Profile 
{ 
    protected override void Configure() 
    { 
     this.CreateMap<MyModel, MyDTO>(); 
    } 
} 
+1

@Sebastian, vielen Dank für die Bearbeitung, den Code zu beschönigen. Ich wusste nicht, wie ich es machen sollte. –

Antwort

14

Die Mapper Klasse eine zu ladende hat statische Eigenschaft Mapper.Engine. Verwenden Sie diese Option, den Motor mit dem Behälter registrieren:

For<IMappingEngine>().Use(() => Mapper.Engine); 

Wenn Sie Ihre Profile müssen geladen werden, bevor der Motor eingespritzt ich diese Konfigurationscode neben dem oben Schnipsel einfügen würde.


aktualisiert

Ihre benutzerdefinierten Registry wie diese wird einmal Dieser Code

class MyRegistry : Registry 
{ 
    public MyRegistry() 
    { 
    For<IMyRepository>().Use<MyRepository>(); 
    For<ILogger>().Use<Logger>(); 

    Mapper.AddProfile(new AutoMapperProfile()); 
    For<IMappingEngine>().Use(() => Mapper.Engine); 
    } 
} 

aussehen würden in Ihrem Bootstrap-Programm und jede Abhängigkeit vom Typ IMappingEngine wird danach mit dem Wert der serviert statische Eigenschaft Mapper.Engine, die mit Ihrer benutzerdefinierten AutoMapperProfile konfiguriert ist.

+0

Arbeitete für mich. Ich kann nicht glauben, dass ich so viel Zeit verloren habe wie ich es versucht habe. –

1

Hier ist, was ich am Ende hatte, da ich nicht herausfinden konnte, wie Sie die Konfiguration auf Mapper.Engine setzen und es in For() übergeben.

+0

Was ist mit 'Mapper.AddProfile()'? –

+0

Sebastian, ich versuche, das statische Mapper-Objekt zu vermeiden, aber wenn ich deiner Linie folge, wäre das die Konfiguration? 'Für () .Verwendung (ctx => { IConfiguration c = Mapper.Configuration; c.AddProfile (); IMappingEngine e = Mapper.Engine; return e; }); ' –

+0

Nicht ganz. Dies würde bedeuten, dass Sie Ihr Profil hinzufügen, wenn eine Komponente eine Abhängigkeit vom Typ "IMappingEngine" benötigt. Bitte beachten Sie das Update zu meiner vorherigen Antwort für den Code, den ich im Sinn hatte. –

1

Ich schrieb einen Blogpost, der meinen AutoMapper mit StructureMap-Setup zeigt. Ich habe spezifische Registries für AutoMapper 3.1.0 (funktioniert auch für 3.1.1) und 3.0.0 und 2.2.1 erstellt.

http://www.martijnburgers.net/post/2013/12/20/My-AutoMapper-setup-for-StructureMap.aspx

+0

Ich habe deinen Beitrag gelesen, aber ich habe immer noch Probleme. Weißt du, was ich hier falsch mache? Http://stackoverflow.com/questions/30081545/inject-isession-into-custom-valuesolver/30084362?noredirect=1#comment48282702_30084362 –

+0

@JoshC. antwortete –

6

Die statische API wird in der Version 5.0 entfernt werden. Verwenden Sie eine MapperConfiguration-Instanz, und speichern Sie sie bei Bedarf statisch. Verwenden Sie CreateMapper, um eine Mapper-Instanz zu erstellen.

in eine neue Version (4.2.0> =), wir sollten IMapper durch DI halten und übergeben.

ein einfacher Configure Service sollte so sein (ASP.NET-Core)

services.AddSingleton<IMapper>(_ => new MapperConfiguration(cfg => 
      { 
       cfg.CreateMap<Foo,Bar>(); 
      }) 
      .CreateMapper()); 

und unsere Service-Schicht (mit Hilfe der Konstruktor Injektion):

public class CrudService<TDocument> : ICrudService<TDocument> 
    { 
     private readonly IMapper _internalMapper; 
     private readonly IRepository<TDocument> _repository; 

     public CrudService(IRepository<TDocument> repository, IMapper mapper)     
     { 
      _internalMapper = mapper; 
      _repository = repository; 
     } 

     public virtual ServiceResult<string> Create<TModel>(TModel foo) 
     { 
      var bar = _internalMapper.Map<TDocument>(foo); 

      try 
      { 
       _repository.Create(bar); 
      } 
      catch (Exception ex) 
      { 
       return ServiceResult<string>.Exception(ex); 
      } 

      return ServiceResult<string>.Okay(entity.Id); 
     } 
} 

consider TDocument as Bar, and TModel as Foo


Update:
AutoMapper 4.2.1 freigegeben - Statisch ist zurück

Nach einem wenig Feedback und Seele suchen und ehrlich müde von mit Fragen beschäftigen, wird ein Teil der statischen API in dieser Freisetzung gestellt. Sie können jetzt (und in Zukunft) verwenden Mapper.Initialize und Mapper.Map

Verwandte Themen