I am trying to create self-hosted System.ServiceModel.Web.WebServiceHost (.NET 4), however I am running into an issue with the constructor. There are three options:

  1. WebServiceHost() a parameterless constructor that seems pointless, as there's no way to specify the type of the service, or even the contract. Reflecting on it, it doesn't do anything- just an empty default constructor that doesn't call base.

  2. WebServiceHost(object singletonInstance, params Uri[] baseAddresses) I don't want a singleton instance, as this is a InstanceContextMode.PerCall class.

  3. WebServiceHost(System.Type serviceType, params Uri[] baseAddresses) The type I want to instantiate as a service doesn't have a parameterless constructor (which is a requirement of this method). I'm using NInject to push the parameters into the constructor. However, I'm trying to run this as a self-hosted test, so I want to avoid DI.

Are there any options along these lines, or will I have to not self-host?

1

There are 1 answers

0
carlosfigueira On BEST ANSWER

To support service classes without parameter-less constructors you need to use an IInstanceProvider implementation which knows how to create the service class. The code below shows one with the WebServiceHost, and you can find more about instance providers at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx.

public class StackOverflow_9997163
{
    [ServiceContract]
    public class Service
    {
        private int increment;
        public Service(int increment)
        {
            this.increment = increment;
        }
        [WebGet]
        public int Add(int x, int y)
        {
            return x + y + increment;
        }
    }
    class MyInstanceProvider : IInstanceProvider
    {
        Func<Service> serviceCreator;
        public MyInstanceProvider(Func<Service> serviceCreator)
        {
            this.serviceCreator = serviceCreator;
        }

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

        public object GetInstance(InstanceContext instanceContext)
        {
            return this.serviceCreator();
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }
    class MyServiceBehavior : IServiceBehavior
    {
        Func<Service> serviceCreator;
        public MyServiceBehavior(Func<Service> serviceCreator)
        {
            this.serviceCreator = serviceCreator;
        }

        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.InstanceProvider = new MyInstanceProvider(this.serviceCreator);
                }
            }
        }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        int currentIncrement = 1;
        host.Description.Behaviors.Add(new MyServiceBehavior(delegate()
        {
            return new Service(currentIncrement++);
        }));
        host.Open();
        Console.WriteLine("Host opened");

        for (int i = 0; i < 10; i++)
        {
            WebClient c = new WebClient();
            Console.WriteLine(c.DownloadString(baseAddress + "/Add?x=6&y=8"));
        }

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}