Reputation: 2001
I am having a WCF application hosted on IIS. I am initializing an IoC container in a custom ServiceHostFactory.
Basically what I would like is to be able to "inject" that IoC Container to each Service instance created within the scope of that ServiceHost.
How would you accomplish that?
Ariel
Upvotes: 1
Views: 939
Reputation: 6684
Like you said you will need a custom ServiceHostFactory that should be used in order to create your services. Something like this:
public class SessionPerCallServiceHostFactory : ServiceHostFactory { public SessionPerCallServiceHostFactory() { } protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { return new SessionPerCallServiceHost(serviceType, baseAddresses); } }
You will also need a ServiceHost responsible for creating the necessary service:
public class SessionPerCallServiceHost : ServiceHost { public SessionPerCallServiceHost() { } public SessionPerCallServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses) { } protected override void OnOpening() { Description.Behaviors.Add(new SessionPerCallServiceBehavior()); base.OnOpening(); } }
With a custom implementation of IServiceBehavior that will be able to provider the InstanceProvider used to create the service instances:
public class SessionPerCallServiceBehavior : IServiceBehavior { public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers) { ChannelDispatcher cd = cdb as ChannelDispatcher; if (cd != null) { foreach (EndpointDispatcher ed in cd.Endpoints) { ed.DispatchRuntime.InstanceProvider = new SessionPerCallInstanceProvider(serviceDescription.ServiceType); } } } } public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) { } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } }
And finally the instance provider that will allow you to use the IoC to inject whatever you want in the requested service instance:
public class SessionPerCallInstanceProvider : IInstanceProvider { private readonly Type _serviceType; public SessionPerCallInstanceProvider(Type serviceType) { _serviceType = serviceType; } public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message) { //I'm creating it without any tricks but you could use your IoC container here return Activator.CreateInstance(_serviceType); } public object GetInstance(InstanceContext instanceContext) { return GetInstance(instanceContext, null); } public void ReleaseInstance(System.ServiceModel.InstanceContext instanceContext, object instance) { } }
Hope it helps!
Upvotes: 2