El uso de la Unidad de Inyección de Dependencia con los servicios WCF

Tengo el siguiente después de hacer algunas investigaciones en las otras preguntas:

MyServiceHost:

public class MyServiceHost : ServiceHost
{
    public MyServiceHost(IUnityContainer 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 DependencyInjectionInstanceProvider(container));
        }
    }
}

DependencyInjectionInstanceProvider:

public class DependencyInjectionInstanceProvider : IInstanceProvider, IContractBehavior 
{     
    private readonly IUnityContainer container;      
    public DependencyInjectionInstanceProvider(IUnityContainer 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.Teardown(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 

} 

MyServiceHostFactory:

    public class MyServiceHostFactory : ServiceHostFactory
{
    private readonly IUnityContainer container;     
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
        return new MyServiceHost(this.container, serviceType, baseAddresses); 
    }
}

Servicio de correo electrónico con un intento de Inyección de Constructor:

public class EmailValidator : IEmailValidator
{
    private IFakeDAL fakeDAL;

    public EmailValidator(IFakeDAL fakeDAL)
    {
        this.fakeDAL = fakeDAL;
    }

    public bool ValidateAddress(string emailAddress)
    {
        Console.WriteLine("Validating: {0}", emailAddress);

        string pattern = @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$";
        return Regex.IsMatch(emailAddress, pattern);
    }
}

Mi Host de la Consola para iniciar el Servicio:

static void Main(string[] args)
    {
        Type serviceType = typeof(EmailValidator);
        Uri serviceUri = new Uri("http://localhost:8080/");

        MyServiceHostFactory shf = new MyServiceHostFactory();
        ServiceHost host = shf.CreateServiceHost(serviceType, serviceUri);
        //ServiceHost host = new ServiceHost(serviceType, serviceUri);
        host.Open();

Mi problema reside en el host de la consola de la lógica. El CreateServiceHost llamada tiene un error de sintaxis, debido a que el primer argumento esperando un Constructor de cadena y no un Tipo. Lo que no entiendo, ya que no acepta un parámetro de Tipo. Además de que no entiendo donde debería estar la asignación de IFakeDAL a una clase concreta. Puedo hacer que en una aplicación.archivo de configuración o debo registrar que en otro lugar?

OriginalEl autor Elim99 | 2011-09-08

3 Kommentare

  1. 7

    ServiceHostFactory es para el alojamiento en el IIS. En el auto de hosting se deberá hacer uso de su derivada ServiceHost directamente. Aquí usted tiene todo el ejemplo, incluyendo la Unidad de configuración.

    Gracias. Parece un muy buen ejemplo. Que realmente puede entender esto. 🙂

    OriginalEl autor Ladislav Mrnka

  2. 3

    Im utilizando las siguientes clases en mi servicio de windows para crear servicios WCF e inyectar las dependencias de usar la unidad.

    UnityInstanceProvider:

    internal class UnityInstanceProvider : IInstanceProvider {
    
        private readonly IUnityContainer container;
        private readonly Type contractType;
    
        public UnityInstanceProvider(IUnityContainer container, Type contractType) {
            this.container = container;
            this.contractType = contractType;
        }
    
        public object GetInstance(InstanceContext instanceContext) {
            return GetInstance(instanceContext, null);
        }
    
        public object GetInstance(InstanceContext instanceContext, Message message) {
            return container.Resolve(contractType);
        }
    
        public void ReleaseInstance(InstanceContext instanceContext, object instance) {
            container.Teardown(instance);
        }
    }

    UnityServiceBehavior:

    public class UnityServiceBehavior : IServiceBehavior {
    
        private readonly IUnityContainer container;
    
        public UnityServiceBehavior(IUnityContainer container) {
            this.container = container;
        }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
        }
    
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) {
        }
    
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
            foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) {
                foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) {
                    if (endpointDispatcher.ContractName != "IMetadataExchange") {
                        string contractName = endpointDispatcher.ContractName;
                        ServiceEndpoint serviceEndpoint = serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName);
                        endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(this.container, serviceEndpoint.Contract.ContractType);
                    }
                }
            }
        }
    }

    UnityServiceHost:

    public class UnityServiceHost : ServiceHost {
    
        private IUnityContainer unityContainer;
    
        public UnityServiceHost(IUnityContainer unityContainer, Type serviceType)
            : base(serviceType) {
            this.unityContainer = unityContainer;
        }
    
        protected override void OnOpening() {
            base.OnOpening();
    
            if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null) {
                this.Description.Behaviors.Add(new UnityServiceBehavior(this.unityContainer));
            }
        }
    }

    Con esto de las clases que usted puede hacer lo siguiente (La configuración de los servicios se realiza en .config):

    UnityContainer container = new UnityContainer();
    UnityServiceHost serviceHost = new UnityServiceHost(container, typeof("Type of Service to host"));
    serviceHost.Open();
    Así que usted es la asignación a las clases concretas en el archivo de configuración?
    ¿Te molesta que muestra la configuración de un servicio en el archivo de configuración?

    OriginalEl autor Jehof

  3. 1

    La CreateServiceHost método espera una matriz de Uri instancias, a fin de tratar este lugar:

    ServiceHost host = shf.CreateServiceHost(serviceType, new[] { serviceUri });

    Puede asignar interfaces de tipos en XML o código, pero me gustaría recomendar el código, ya que XML tiene un exceso de gastos de mantenimiento.

    La Main método es una excelente La Composición De La Raíz, pero si desea configurar el contenedor en ese nivel, tendrás la necesidad de pasar de la Main método para MyServiceHostFactory – que está perfectamente bien cuando alojar el servicio en una aplicación de consola, pero no funcionará si usted desea alojar en IIS, donde MyServiceHostFactory debe ser la Composición de la Raíz, ya que IIS requiere un constructor predeterminado.

    +1 por el comentario en donde la composición de la raíz debe ser. BTW, amar el libro de Mark.

    OriginalEl autor Mark Seemann

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea