WCF prend en charge Injection Constructeur, mais vous devez passer quelques cerceaux pour y arriver. La clé réside dans l'écriture d'un ServiceHostFactory personnalisé. Bien que cela aussi, doit avoir un constructeur par défaut, vous pouvez l'utiliser pour câbler tous les comportements corrects. Par exemple, j'ai récemment écrit un qui utilise Castle Windsor pour câbler les dépendances pour l'implémentation du service. La mise en œuvre de CreateServiceHost fait simplement ceci:
return new WindsorServiceHost(this.container, serviceType, baseAddresses);
où this.container
est un IWindsorContainer configuré.
WindsorServiceHost ressemble à ceci:
public class WindsorServiceHost : ServiceHost
{
public WindsorServiceHost(IWindsorContainer container, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new WindsorInstanceProvider(container));
}
}
}
et WindsorInstanceProvider ressemble à ceci:
public class WindsorInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IWindsorContainer container;
public WindsorInstanceProvider(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
var serviceType = instanceContext.Host.Description.ServiceType;
return this.container.Resolve(serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
this.container.Release(instance);
}
#endregion
#region IContractBehavior Members
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
#endregion
}
Cela peut ressembler à beaucoup, mais notez qu'il est réutilisable, le code d'usage général qui a plutôt faible complexité cyclomatique.
Vous pouvez suivre le même idiome de codage pour implémenter l'injection de dépendances avec un autre conteneur DI ou en utilisant DI de Poor Man.
Voici un older writeup de cet idiome qui utilise DI de Poor Man.
utilisez-vous un conteneur IoC? et si oui lequel? – Fabiano
Je n'utilise pas encore de conteneur IoC côté serveur. Je prévois d'en présenter un maintenant. J'utilise Unity côté client (comme avec Prism), mais envisage d'utiliser StructureMap sur le serveur. Ouvert à tous. – stiank81