Chciałbym przekazać wartości do konstruktora w klasie implementującej moją usługę.
Jednak ServiceHost pozwala mi tylko przekazać nazwę typu do utworzenia, a nie jakie argumenty przekazać do jego kontrstruktora.
Chciałbym móc przejść do fabryki, która tworzy mój obiekt usługowy.
Co znalazłem do tej pory:
- Zachowanie iniekcji zależności WCF, które jest czymś więcej niż to, czego szukam i wydaje się być zbyt złożone dla moich potrzeb.
wcf
dependency-injection
factory-pattern
Ian Ringrose
źródło
źródło
Odpowiedzi:
Trzeba zaimplementować kombinacji zwyczaju
ServiceHostFactory
,ServiceHost
iIInstanceProvider
.Biorąc pod uwagę usługę z tym podpisem konstruktora:
Oto przykład, który może uruchomić MyService:
Zarejestruj MyServiceHostFactory w pliku MyService.svc lub użyj MyServiceHost bezpośrednio w kodzie dla scenariuszy samodzielnego hostingu.
Możesz łatwo uogólnić to podejście, aw rzeczywistości niektóre DI Containers już to zrobiły (cue: Windsor's WCF Facility).
źródło
protected
że nie mogę tego nazwać sam z Main ()dep
do każdego dostawcy InstanceProvider kontraktu . Możesz zrobić:ImplementedContracts.Values.First(c => c.Name == "IMyService").ContractBehaviors.Add(new MyInstanceProvider(dep));
gdzieIMyService
jest interfejs kontraktu twojegoMyService(IDependency dep)
. Więc wstrzykujIDependency
tylko do InstanceProvider, który faktycznie tego potrzebuje.Możesz po prostu utworzyć i umieścić swoją instancję
Service
i przekazać tę instancję doServiceHost
obiektu. Jedyne, co musisz zrobić, to dodać[ServiceBehaviour]
atrybut dla swojej usługi i oznaczyć wszystkie zwracane obiekty[DataContract]
atrybutem.Oto makieta:
i zastosowanie:
Mam nadzieję, że komuś to ułatwi życie.
źródło
InstanceContextMode.Single
).Odpowiedź Marka z znakiem
IInstanceProvider
jest poprawna.Zamiast używać niestandardowego ServiceHostFactory, możesz również użyć atrybutu niestandardowego (powiedzmy
MyInstanceProviderBehaviorAttribute
). Wyprowadź go zAttribute
,IServiceBehavior
spraw , aby zaimplementował i zaimplementujIServiceBehavior.ApplyDispatchBehavior
metodę taką jakNastępnie zastosuj atrybut do klasy implementacji usługi
Trzecia opcja: możesz również zastosować zachowanie usługi za pomocą pliku konfiguracyjnego.
źródło
Pracowałem na podstawie odpowiedzi Marka, ale (przynajmniej dla mojego scenariusza) było to niepotrzebnie skomplikowane. Jeden z
ServiceHost
konstruktorów akceptuje wystąpienie usługi, które można przekazać bezpośrednio zServiceHostFactory
implementacji.Aby odnieść się do przykładu Marka, wyglądałoby to tak:
źródło
instance
. To może mieć wpływ na wydajność, ale nie musi. Jeśli chcesz mieć możliwość obsługi współbieżnych żądań, cały graf obiektu musi być bezpieczny dla wątków, w przeciwnym razie uzyskasz niedeterministyczne, niepoprawne zachowanie. Jeśli możesz zagwarantować bezpieczeństwo wątków, moje rozwiązanie jest rzeczywiście niepotrzebnie skomplikowane. Jeśli nie możesz tego zagwarantować, wymagane jest moje rozwiązanie.Chrzanić to… Połączyłem wzorce wstrzykiwania zależności i lokalizatora usług (ale przeważnie jest to nadal wstrzykiwanie zależności i odbywa się to nawet w konstruktorze, co oznacza, że możesz mieć stan tylko do odczytu).
Zależności usługi są jasno określone w kontrakcie jej zagnieżdżonej
Dependencies
klasy. Jeśli używasz kontenera IoC (takiego, który jeszcze nie naprawia bałaganu WCF), możesz skonfigurować go do tworzeniaDependencies
wystąpienia zamiast usługi. W ten sposób uzyskujesz ciepłe, rozmyte uczucie, które daje twój kontener, a jednocześnie nie musisz przeskakiwać przez zbyt wiele obręczy narzuconych przez WCF.Nie zamierzam tracić snu z powodu tego podejścia. Nikt inny też nie powinien. W końcu kontener you IoC to duży, gruby, statyczny zbiór delegatów, który tworzy rzeczy dla Ciebie. Co dodaje jeszcze jednego?
źródło
Mieliśmy ten sam problem i rozwiązaliśmy go w następujący sposób. To proste rozwiązanie.
W programie Visual Studio po prostu utwórz normalną aplikację usługi WCF i usuń jej interfejs. Pozostaw plik .cs na miejscu (po prostu zmień jego nazwę) i otwórz ten plik cs i zastąp nazwę interfejsu oryginalną nazwą klasy, która implementuje logikę usługi (w ten sposób klasa usługi używa dziedziczenia i zastępuje rzeczywistą implementację). Dodaj domyślny konstruktor, który wywołuje konstruktory klasy bazowej, na przykład:
Klasa bazowa MyService to rzeczywista implementacja usługi. Ta klasa bazowa nie powinna mieć konstruktora bez parametrów, ale tylko konstruktory z parametrami, które akceptują zależności.
Usługa powinna używać tej klasy zamiast oryginalnej MyService.
To proste rozwiązanie i działa jak marzenie :-D
źródło
To było bardzo pomocne rozwiązanie - szczególnie dla kogoś, kto jest początkującym programistą WCF. Chciałem opublikować małą wskazówkę dla wszystkich użytkowników, którzy mogą używać tego w usłudze hostowanej przez IIS. MyServiceHost musi dziedziczyć WebServiceHost , a nie tylko ServiceHost.
Spowoduje to utworzenie wszystkich niezbędnych powiązań itp. Dla punktów końcowych w usługach IIS.
źródło
Używam zmiennych statycznych mojego typu. Nie jestem pewien, czy to najlepszy sposób, ale dla mnie działa:
Podczas tworzenia wystąpienia hosta usługi wykonuję następujące czynności:
źródło