Andry
Andry

Reputation: 16845

Explicitly calling a service constructor when hosting a WCF web service on IIS

I want to host a WCF service of mine on Microsoft IIS (IIS hosting).

To do this, I created my service:

// The service
public class MyService : IMyService {
    // Ctors
    public MyService() {
        // Def ctor: I don't want to call it
    }
    public MyService(...) : this() {
        // Parametric ctor, I want to call it!
    }
   ...
}

// The contract
[ServiceContract]
public interface IMyService {
    ...
}

I created a svc file (a good approach to give a base address to my service):

<@ServiceHost Service="MyService" @>

But doing so, when hosting my service (simply creating a virtual directory in IIS pointing to the folder where my application resides, the project directory usually), IIS will call the default constructor.

How do I make IIS call a different constructor?

PS: I know that it is possible to specify a HostServiceFactory. Is it something I should use here? It gives me back the factory and a host. For the host, I cannot act on the host passed parameters. However, how do I solve this problem?

NOTE: I understood that many solutions are based on Inversion of control (IoC) and several IoC frameworks like Unity, Castle Project and Spring.NET. However I would not really use them at all. Can WCF make this on its own? I cannot accept that WCF cannot let a programmer host a service by constructing it in the appropriate manner...

Upvotes: 4

Views: 3123

Answers (3)

Aske B.
Aske B.

Reputation: 6609

If all you need is to call a specific constructor in your service, then you only need to implement an IInstanceProvider and attach an IServiceBehavior to your service:

IInstanceProvider

public class ServiceInstanceProvider : IInstanceProvider
{
    public object GetInstance(InstanceContext instanceContext)
    {
        return this.GetInstance(instanceContext, null);
    }

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

    public void ReleaseInstance(InstanceContext instanceContext, object instance)
    {}
}

IServiceBehavior as Attribute

public class InstanceProviderBehaviorAttribute : Attribute, IServiceBehavior
{
    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)
            {
                if (!ed.IsSystemEndpoint)
                {
                    ed.DispatchRuntime.InstanceProvider = new ServiceInstanceProvider();
                }
            }
        }
    }

    public void Validate(ServiceDescription serviceDescription,
            ServiceHostBase serviceHostBase)
    {}
}

MyService with the custom ServiceBehavior Attribute

[InstanceProviderBehavior]
public class MyService : IMyService {
    public MyService() { }
    public MyService(...) : this() {
        ...
    }
   ...
}

More info on this here:

Upvotes: 0

xelibrion
xelibrion

Reputation: 2234

Take a look at Castle WCF Facility (I use this one in production) or Autofac WCF integration

Upvotes: 0

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364279

You must write several custom classes to support creating service with parameters:

  • Custom class implementing IInstanceProvider. This class will be responsible for creating your service instance with your non default constructor.
  • Custom class implementing IServiceBehavior. This class will be responsible for adding custom instance provider into endpoint dispatcher.
  • Custom ServiceHost which will apply your behavior.
  • Custom ServiceHostFactory which will instantiate your custom service host. You will reference this factory from .svc file.

This is generally the same as building support for dependency injection. You can check for example this article.

Upvotes: 6

Related Questions