Reputation: 16845
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
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:
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)
{}
}
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)
{}
}
[InstanceProviderBehavior]
public class MyService : IMyService {
public MyService() { }
public MyService(...) : this() {
...
}
...
}
More info on this here:
Upvotes: 0
Reputation: 2234
Take a look at Castle WCF Facility (I use this one in production) or Autofac WCF integration
Upvotes: 0
Reputation: 364279
You must write several custom classes to support creating service with parameters:
IInstanceProvider
. This class will be responsible for creating your service instance with your non default constructor.IServiceBehavior
. This class will be responsible for adding custom instance provider into endpoint dispatcher.ServiceHost
which will apply your behavior.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