¿Cómo paso valores al constructor de mi servicio wcf?

Resuelto Ian Ringrose asked hace 14 años • 10 respuestas

Me gustaría pasar valores al constructor de la clase que implementa mi servicio.

Sin embargo, ServiceHost solo me permite pasar el nombre del tipo a crear, no qué argumentos pasar a su constructor.

Me gustaría poder pasar por una fábrica que cree mi objeto de servicio.

Lo que he encontrado hasta ahora:

  • Comportamiento de inyección de dependencia de WCF , que es más de lo que estoy buscando y parece demasiado complejo para mis necesidades.
Ian Ringrose avatar Mar 16 '10 20:03 Ian Ringrose
Aceptado

Necesitará implementar una combinación de custom ServiceHostFactoryy ServiceHost.IInstanceProvider

Dado un servicio con esta firma de constructor:

public MyService(IDependency dep)

Aquí hay un ejemplo que puede activar MyService:

public class MyServiceHostFactory : ServiceHostFactory
{
    private readonly IDependency dep;

    public MyServiceHostFactory()
    {
        this.dep = new MyClass();
    }

    protected override ServiceHost CreateServiceHost(Type serviceType,
        Uri[] baseAddresses)
    {
        return new MyServiceHost(this.dep, serviceType, baseAddresses);
    }
}

public class MyServiceHost : ServiceHost
{
    public MyServiceHost(IDependency dep, Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
        if (dep == null)
        {
            throw new ArgumentNullException("dep");
        }

        foreach (var cd in this.ImplementedContracts.Values)
        {
            cd.Behaviors.Add(new MyInstanceProvider(dep));
        }
    }
}

public class MyInstanceProvider : IInstanceProvider, IContractBehavior
{
    private readonly IDependency dep;

    public MyInstanceProvider(IDependency dep)
    {
        if (dep == null)
        {
            throw new ArgumentNullException("dep");
        }

        this.dep = dep;
    }

    #region IInstanceProvider Members

    public object GetInstance(InstanceContext instanceContext, Message message)
    {
        return this.GetInstance(instanceContext);
    }

    public object GetInstance(InstanceContext instanceContext)
    {
        return new MyService(this.dep);
    }

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {
        var disposable = instance as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }

    #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
}

Registre MyServiceHostFactory en su archivo MyService.svc o use MyServiceHost directamente en el código para escenarios de autohospedaje.

Puede generalizar fácilmente este enfoque y, de hecho, algunos contenedores DI ya lo han hecho por usted (pista: instalación WCF de Windsor).

Mark Seemann avatar Mar 16 '2010 14:03 Mark Seemann

Simplemente puede crear una instancia suya Servicey pasar esa instancia al ServiceHostobjeto. Lo único que tienes que hacer es agregar un [ServiceBehaviour]atributo para tu servicio y marcar todos los objetos devueltos con [DataContract]un atributo.

Aquí hay una maqueta:

namespace Service
{
    [ServiceContract]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class MyService
    {
        private readonly IDependency _dep;

        public MyService(IDependency dep)
        {
            _dep = dep;
        }

        public MyDataObject GetData()
        {
            return _dep.GetData();
        }
    }

    [DataContract]
    public class MyDataObject
    {
        public MyDataObject(string name)
        {
            Name = name;
        }

        public string Name { get; private set; }
    }

    public interface IDependency
    {
        MyDataObject GetData();
    }
}

y el uso:

var dep = new Dependecy();
var myService = new MyService(dep);
var host = new ServiceHost(myService);

host.Open();

Espero que esto le haga la vida más fácil a alguien.

kerim avatar Feb 10 '2014 17:02 kerim