Je voudrais transmettre des valeurs au constructeur sur la classe qui implémente mon service.
Cependant ServiceHost ne me laisse passer que le nom du type à créer, pas les arguments à passer à son constructeur.
Je voudrais pouvoir passer dans une fabrique qui crée mon objet de service.
Ce que j'ai trouvé jusqu'à présent:
- Comportement d'injection de dépendance WCF qui est plus que ce que je recherche et semble trop complexe pour mes besoins.
wcf
dependency-injection
factory-pattern
Ian Ringrose
la source
la source
Réponses:
Vous aurez besoin de mettre en œuvre une combinaison de la coutume
ServiceHostFactory
,ServiceHost
etIInstanceProvider
.Étant donné un service avec cette signature de constructeur:
Voici un exemple qui peut lancer MyService:
Enregistrez MyServiceHostFactory dans votre fichier MyService.svc ou utilisez MyServiceHost directement dans le code pour les scénarios d'auto-hébergement.
Vous pouvez facilement généraliser cette approche, et en fait certains conteneurs DI l'ont déjà fait pour vous (cue: Windsor's WCF Facility).
la source
protected
je ne peux pas l'appeler moi-même depuis Main ()dep
dans chaque InstanceProvider de contrat . Vous pourriez faire:ImplementedContracts.Values.First(c => c.Name == "IMyService").ContractBehaviors.Add(new MyInstanceProvider(dep));
oùIMyService
est une interface de contrat de votreMyService(IDependency dep)
. Donc, injectezIDependency
uniquement dans InstanceProvider qui en a réellement besoin.Vous pouvez simplement créer une instance de votre
Service
et la transmettre à l'ServiceHost
objet. La seule chose que vous avez à faire est d'ajouter un[ServiceBehaviour]
attribut pour votre service et de marquer tous les objets retournés avec un[DataContract]
attribut.Voici une maquette:
et l'utilisation:
J'espère que cela facilitera la vie de quelqu'un.
la source
InstanceContextMode.Single
).La réponse de Mark avec le
IInstanceProvider
est correcte.Au lieu d'utiliser le ServiceHostFactory personnalisé, vous pouvez également utiliser un attribut personnalisé (par exemple
MyInstanceProviderBehaviorAttribute
). Dérivez-leAttribute
, faites-le implémenterIServiceBehavior
et implémentez laIServiceBehavior.ApplyDispatchBehavior
méthode commeEnsuite, appliquez l'attribut à votre classe d'implémentation de service
La troisième option: vous pouvez également appliquer un comportement de service à l'aide du fichier de configuration.
la source
J'ai travaillé à partir de la réponse de Mark, mais (pour mon scénario du moins), c'était inutilement complexe. L'un des
ServiceHost
constructeurs accepte une instance du service, que vous pouvez transmettre directement depuis l'ServiceHostFactory
implémentation.Pour reprendre l'exemple de Mark, cela ressemblerait à ceci:
la source
instance
. Cela peut ou non affecter les performances. Si vous voulez être en mesure de gérer des demandes simultanées, cela intégralité de ce graphique d'objet doit être thread-safe, ou vous obtiendrez un comportement incorrect non déterministe. Si vous pouvez garantir la sécurité des threads, ma solution est en effet inutilement complexe. Si vous ne pouvez pas garantir cela, ma solution est requise.Vissez… J'ai mélangé les modèles d'injection de dépendances et de localisateur de service (mais surtout c'est toujours l'injection de dépendances et cela a même lieu dans le constructeur, ce qui signifie que vous pouvez avoir un état en lecture seule).
Les dépendances du service sont clairement spécifiées dans le contrat de sa
Dependencies
classe imbriquée . Si vous utilisez un conteneur IoC (qui ne résout pas déjà le désordre WCF pour vous), vous pouvez le configurer pour créer l'Dependencies
instance au lieu du service. De cette façon, vous obtenez la sensation chaleureuse et floue que votre conteneur vous donne sans avoir à sauter à travers trop de cerceaux imposés par WCF.Je ne vais pas perdre de sommeil avec cette approche. Personne d'autre non plus. Après tout, votre conteneur IoC est une grande collection statique de délégués qui crée des choses pour vous. Qu'est-ce qui en ajoute un de plus?
la source
Nous étions confrontés à ce même problème et l'avons résolu de la manière suivante. C'est une solution simple.
Dans Visual Studio, créez simplement une application de service WCF normale et supprimez son interface. Laissez le fichier .cs en place (renommez-le simplement) et ouvrez ce fichier cs et remplacez le nom de l'interface par votre nom de classe d'origine qui implémente la logique de service (de cette façon, la classe de service utilise l'héritage et remplace votre implémentation réelle). Ajoutez un constructeur par défaut qui appelle les constructeurs de la classe de base, comme ceci:
La classe de base MyService est l'implémentation réelle du service. Cette classe de base ne doit pas avoir de constructeur sans paramètre, mais uniquement des constructeurs avec des paramètres qui acceptent les dépendances.
Le service doit utiliser cette classe au lieu du MyService d'origine.
C'est une solution simple et fonctionne comme un charme :-D
la source
C'était une solution très utile - en particulier pour quelqu'un qui est un codeur WCF novice. Je voulais publier un petit conseil pour tous les utilisateurs qui pourraient l'utiliser pour un service hébergé par IIS. MyServiceHost doit hériter de WebServiceHost , pas seulement de ServiceHost.
Cela créera toutes les liaisons nécessaires, etc. pour vos points de terminaison dans IIS.
la source
J'utilise des variables statiques de mon type. Je ne sais pas si c'est le meilleur moyen, mais cela fonctionne pour moi:
Lorsque j'instancie l'hôte de service, je fais ce qui suit:
la source