Ich möchte Werte an den Konstruktor der Klasse übergeben, die meinen Service implementiert.
Mit ServiceHost kann ich jedoch nur den Namen des zu erstellenden Typs übergeben, nicht die Argumente, die an den Konstruktor übergeben werden sollen.
Ich möchte in der Lage sein, eine Fabrik zu übergeben, die mein Serviceobjekt erstellt.
Was ich bisher gefunden habe:
- WCF-Abhängigkeitsinjektionsverhalten, das mehr ist als das, wonach ich suche und für meine Bedürfnisse überkomplex zu sein scheint.
wcf
dependency-injection
factory-pattern
Ian Ringrose
quelle
quelle
Antworten:
Sie müssen eine Kombination von benutzerdefinierten implementieren
ServiceHostFactory
,ServiceHost
undIInstanceProvider
.Bei einem Dienst mit dieser Konstruktorsignatur:
Hier ist ein Beispiel, das MyService starten kann:
Registrieren Sie MyServiceHostFactory in Ihrer MyService.svc-Datei oder verwenden Sie MyServiceHost direkt im Code für Self-Hosting-Szenarien.
Sie können diesen Ansatz leicht verallgemeinern, und tatsächlich haben einige DI-Container dies bereits für Sie getan (Stichwort: WCF-Einrichtung von Windsor).
quelle
protected
kann ich sie nicht selbst von Main ()dep
in den InstanceProvider jedes Vertrags injiziert haben . Sie könnten tun:ImplementedContracts.Values.First(c => c.Name == "IMyService").ContractBehaviors.Add(new MyInstanceProvider(dep));
WoIMyService
ist eine Vertragsschnittstelle von IhnenMyService(IDependency dep)
. Spritzen Sie alsoIDependency
nur in InstanceProvider, die es tatsächlich benötigen.Sie können einfach eine Instanz von erstellen und
Service
diese Instanz an dasServiceHost
Objekt übergeben. Sie müssen lediglich ein[ServiceBehaviour]
Attribut für Ihren Dienst hinzufügen und alle zurückgegebenen Objekte mit[DataContract]
Attribut markieren .Hier ist ein Modell:
und die Verwendung:
Ich hoffe, das wird jemandem das Leben leichter machen.
quelle
InstanceContextMode.Single
).Marks Antwort mit dem
IInstanceProvider
ist richtig.Anstatt die benutzerdefinierte ServiceHostFactory zu verwenden, können Sie auch ein benutzerdefiniertes Attribut verwenden (z
MyInstanceProviderBehaviorAttribute
. B. ). Leiten Sie es abAttribute
, lassen Sie es implementierenIServiceBehavior
und implementieren Sie dieIServiceBehavior.ApplyDispatchBehavior
Methode wieWenden Sie dann das Attribut auf Ihre Service-Implementierungsklasse an
Die dritte Option: Sie können ein Dienstverhalten auch mithilfe der Konfigurationsdatei anwenden.
quelle
Ich habe nach Marks Antwort gearbeitet, aber (zumindest für mein Szenario) war es unnötig komplex. Einer der
ServiceHost
Konstruktoren akzeptiert eine Instanz des Dienstes, die Sie direkt von derServiceHostFactory
Implementierung übergeben können.Um Marks Beispiel zu huckepack zu nehmen, würde es so aussehen:
quelle
instance
. Dies kann die Leistung beeinträchtigen oder nicht. Wenn Sie in der Lage sein möchten, gleichzeitige Anforderungen zu verarbeiten, muss das gesamte Objektdiagramm threadsicher sein. Andernfalls wird ein nicht deterministisches, falsches Verhalten angezeigt. Wenn Sie die Thread-Sicherheit gewährleisten können, ist meine Lösung in der Tat unnötig komplex. Wenn Sie das nicht garantieren können, ist meine Lösung erforderlich.Scheiß drauf ... Ich habe die Muster der Abhängigkeitsinjektion und des Service-Locators gemischt (aber meistens ist es immer noch die Abhängigkeitsinjektion und sie findet sogar im Konstruktor statt, was bedeutet, dass Sie einen schreibgeschützten Status haben können).
Die Abhängigkeiten des Dienstes sind im Vertrag seiner verschachtelten
Dependencies
Klasse klar angegeben . Wenn Sie einen IoC-Container verwenden (der das WCF-Chaos noch nicht für Sie behebt), können Sie ihn so konfigurieren, dass dieDependencies
Instanz anstelle des Dienstes erstellt wird. Auf diese Weise erhalten Sie das warme, unscharfe Gefühl, das Ihr Container Ihnen vermittelt, während Sie nicht durch zu viele von WCF auferlegte Reifen springen müssen.Ich werde bei diesem Ansatz keinen Schlaf verlieren. Weder sollte jemand anderes. Schließlich ist Ihr IoC-Container eine große, fette, statische Sammlung von Delegierten, die Dinge für Sie erstellt. Was fügt noch einen hinzu?
quelle
Wir standen vor dem gleichen Problem und haben es auf folgende Weise gelöst. Es ist eine einfache Lösung.
Erstellen Sie in Visual Studio einfach eine normale WCF-Dienstanwendung und entfernen Sie die Schnittstelle. Lassen Sie die CS-Datei an Ort und Stelle (benennen Sie sie einfach um) und öffnen Sie diese CS-Datei. Ersetzen Sie den Namen der Schnittstelle durch Ihren ursprünglichen Klassennamen, der die Servicelogik implementiert (auf diese Weise verwendet die Serviceklasse die Vererbung und ersetzt Ihre tatsächliche Implementierung). Fügen Sie einen Standardkonstruktor hinzu, der die Konstruktoren der Basisklasse wie folgt aufruft:
Die MyService-Basisklasse ist die eigentliche Implementierung des Dienstes. Diese Basisklasse sollte keinen parameterlosen Konstruktor haben, sondern nur Konstruktoren mit Parametern, die die Abhängigkeiten akzeptieren.
Der Dienst sollte diese Klasse anstelle des ursprünglichen MyService verwenden.
Es ist eine einfache Lösung und funktioniert wie ein Zauber :-D
quelle
Dies war eine sehr hilfreiche Lösung - insbesondere für jemanden, der ein unerfahrener WCF-Codierer ist. Ich wollte einen kleinen Tipp für alle Benutzer veröffentlichen, die diesen für einen von IIS gehosteten Dienst verwenden. MyServiceHost muss WebServiceHost erben , nicht nur ServiceHost.
Dadurch werden alle erforderlichen Bindungen usw. für Ihre Endpunkte in IIS erstellt.
quelle
Ich benutze statische Variablen meines Typs. Ich bin mir nicht sicher, ob dies der beste Weg ist, aber es funktioniert bei mir:
Wenn ich den Service-Host instanziiere, gehe ich wie folgt vor:
quelle