WCF admite Constructor Injection, pero debe pasar unos aros para llegar allí. La clave está en escribir un ServiceHostFactory personalizado. Si bien eso también debe tener un constructor predeterminado, puede usarlo para cablear todos los comportamientos correctos.
Como ejemplo, recientemente escribí uno que usa Castle Windsor para conectar dependencias para la implementación del servicio. La implementación de CreateServiceHost simplemente hace esto:
return new WindsorServiceHost(this.container, serviceType, baseAddresses);
donde this.container
es una IWindsorContainer configurado.
WindsorServiceHost se ve así:
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));
}
}
}
y WindsorInstanceProvider se ve así:
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
}
Esto puede parecer mucho, pero darse cuenta de que es reutilizable, el código de uso general que tiene un lugar baja complejidad ciclomática.
Puede seguir el mismo idioma de codificación para implementar Dependency Injection con otro contenedor DI o utilizando la DI de Poor Man.
Aquí hay un older writeup de este idioma que usa la DI de Poor Man.
¿está utilizando un contenedor IoC? y si es así, ¿cuál? – Fabiano
Todavía no estoy usando un contenedor de IoC en el servidor. Planeando presentar uno ahora. Estoy usando Unity en el lado del cliente (como venía con Prism), pero considere usar StructureMap en el servidor. Abierto para cualquiera realmente. – stiank81