Wenn Automapper Dienste verwendet, die von einem Autofac mit WebApi erstellt wurden

8

Ich verwende WebAPI + Autofac + Automapper mit einem Repository für den Datenzugriff. Ich muss meinen Domain-Entitäten ein Modell zuordnen, insbesondere muss ich einen Identitätswert in die tatsächliche Entität konvertieren. Keine große Sache, oder? Ich habe das in MVC ohne Probleme gemacht. Ich werde vereinfachen, was ich mache, um das Wesentliche zu enthüllen.

%Vor%

Repositories sind bei Autofac registriert und werden wegen der Sitzungs- / Transaktionsverwaltung als InstancePerApiRequest verwaltet. Also muss ich meinen Konverter im selben Umfang registrieren:

%Vor%

Die Automapper-Konfiguration sieht ungefähr so ​​aus:

%Vor%

Also hier ist der Teil, der saugt. Ich muss verstehen, dass Automapper den ConstructServicesUsing Guy benötigt, bevor du deine Config erstellst. Wenn Sie es später einstellen, wird es nicht verwendet. Das obige Beispiel funktioniert nicht, da container der Root-Bereich ist. Wenn ich versuche, EntityConverter<TestEntity> aufzulösen, wird sich Autofac darüber beschweren, dass der angeforderte Typ für einen anderen Bereich registriert ist, und der, in dem Sie sich befinden, ist es nicht. Macht Sinn, ich möchte den von WebApi erstellten Bereich.

Lassen Sie mich eine Sekunde pausieren und eine Tatsache über die WebApi-Abhängigkeitsinjektion behandeln (ich glaube nicht, dass dies Autofac-spezifisch ist). WebApi erstellt eine IDependencyScope für die Anfrage und speichert sie in HttpRequestMessage.Properties . Ich kann es nicht wieder zurückbekommen, wenn ich nicht auf dieselbe HttpRequestMessage -Instanz zugreifen kann. Mein AsInstancePerApiRequest scoping auf IRepository und mein Konverter verlassen sich daher auf IDependencyScope .

Also, das ist wirklich das Fleisch und die Kartoffeln des Problems, und ich frustrierte wirklich mit diesem Unterschied von MVC. Du kannst es nicht tun

%Vor%

Das entspricht der Verwendung von container.Resolve . Ich kann nicht

verwenden %Vor%

weil A), das einen neuen Bereich neben dem einen erstellt, den ich eigentlich möchte, B) lässt mich nicht wirklich den neuen Bereich aufräumen, den ich erstellt habe. Die Verwendung von Service Locator ist eine neue Möglichkeit, das gleiche Problem zu haben. Ich komme nicht zu dem Umfang, den WebApi benutzt. Wenn mein Konverter und seine Abhängigkeiten eine einzelne Instanz oder eine Instanz pro Abhängigkeit wären, wäre das kein Problem, aber sie sind es nicht, so ist es, und das Ändern würde viele Probleme für mich erzeugen.

Jetzt kann ich AutoMapper config mit Autofac erstellen und es als eine einzelne Instanz registrieren. Ich kann sogar pro-Anfrage IMappingEngine Instanzen erstellen. Aber das bringt mir nichts, wenn der Dienstkonstruktor immer den einzigen Delegaten verwendet, den Sie am Anfang registrieren, der keinen Zugriff auf den aktuellen Bereich hat. Wenn ich diesen Delegaten für jede Mapping-Engine-Instanz ändern könnte, könnte ich geschäftlich tätig sein. Aber ich kann nicht.

Also was kann ich tun?

    
HackedByChinese 11.09.2013, 04:01
quelle

3 Antworten

6

Eine weitere Option, die dieses Mal eingebaut wird, ist die Verwendung der pro-map-Optionen:

%Vor%

Berücksichtigen Sie nicht die globale IoC-Konfiguration in Ihrer Mapping-Konfiguration.

Eine andere Option ist die Verwendung Ihres IoC-Tools, um zu konfigurieren, wie die MappingEngine instanziiert wird:

%Vor%

Der erste ist nur Mapper.Configuration, der zweite sollte wahrscheinlich ein Singleton sein und der dritte, den Sie mit der aktuellen geschachtelten Container-Auflösung ausfüllen können. Dies würde es vereinfachen, die Map-Überladung jedes Mal aufzurufen.

    
Jimmy Bogard 13.01.2015, 14:25
quelle
4

Update: Der Automapper wurde aktualisiert, um diese Funktion zu unterstützen. Siehe @Jimmy Bogards Antwort

Diese Lösung könnte nicht sehr nett sein, aber es funktioniert. Die Lösung bezieht sich auf WebAPI 2, über frühere Versionen bin ich mir nicht sicher.

In WebAPI 2 können Sie die aktuelle IDependencyScope von der aktuellen HttpRequestMessage via GetDependencyScope() Erweiterungsmethode abrufen. Der aktuelle HttpRequestMessage wird in der Eigenschaft Items des aktuellen HttpContext gespeichert. Zu wissen, dass Ihre Fabrik aussehen könnte:

%Vor%     
Alexandr Nikitin 01.07.2014 11:43
quelle
1

Dies kann oder kann nicht für Sie geeignet sein .. aber hier geht:

Wir haben das kürzlich gemacht .. für Modellbinder in MVC. Unsere Modellbinder (auf GET-Anfragen) verwenden jetzt Ninject-Managed Services, um Modelle zu erstellen.

Im Grunde injizieren wir eine Fabrik (mit Ninjects Factories-Erweiterung ... vielleicht gibt es eine ähnliche für Autofac) in eine "AutomapperBootstrapper" -Klasse, die wiederum Automapper-Mapping Profile erstellt und sie zu Automapper hinzufügt. Etwas so:

%Vor%

Die Zuordnungen Profile selbst verwenden MapFrom() , was jedes Mal ausgewertet wird, wenn eine Zuordnung stattfindet. Etwas wie das:

%Vor%

Jedes Mal, wenn der Modellbinder gestartet wird, werden alle Abhängigkeiten für die Anfrage von Ninject noch verdrahtet und alles wird gefiltert.

(Für diejenigen, die daran interessiert sind, lässt uns dieses Setup im Wesentlichen Folgendes tun: /Area/Controller/Action/12 , und unsere Methode für die Controller-Aktion ist dies:

%Vor%

).

    
Simon Whitehead 11.09.2013 04:23
quelle