UnityServiceHostFactory, a WCF host factory:
using System;
using System.ServiceModel.Activation;
using System.ServiceModel;
using Infrastructure.IoContainer;
namespace Services.Host.Infrastructure
{
public abstract class UnityServiceHostFactory : ServiceHostFactoryBase
{
private readonly IUnityConfiguration _unityConfiguration;
protected UnityServiceHostFactory(IUnityConfiguration unityConfiguration)
{
_unityConfiguration = unityConfiguration;
}
public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
{
var serviceType = Type.GetType(constructorString);
var host = new UnityServiceHost(serviceType, baseAddresses);
Unity.Configure(_unityConfiguration);
host.Container = Unity.Current;
return host;
}
}
}
UnityServiceHost, a WCF Service host:
using System;
using System.ServiceModel;
using Microsoft.Practices.Unity;
namespace Services.Host.Infrastructure
{
public class UnityServiceHost : ServiceHost
{
public IUnityContainer Container { set; get; }
public UnityServiceHost() : base() {}
public UnityServiceHost(
Type serviceType,
params Uri[] baseAddresses) : base(serviceType, baseAddresses) {}
protected override void OnOpening()
{
if (Container == null)
throw new ApplicationException("The UnityServiceHost's Container property can't be null");
new UnityServiceBehavior(Container).AddToHost(this);
base.OnOpening();
}
}
}
UnityServiceBehavior, a WCF Service behavior:
using System.Linq;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel;
using Microsoft.Practices.Unity;
using System.ServiceModel.Channels;
using System.Collections.ObjectModel;
namespace Services.Host.Infrastructure
{
public class UnityServiceBehavior : IServiceBehavior
{
public UnityInstanceProvider InstanceProvider { get; set; }
private ServiceHost _serviceHost;
public UnityServiceBehavior()
{
InstanceProvider = new UnityInstanceProvider();
}
public UnityServiceBehavior(IUnityContainer unity)
{
InstanceProvider = new UnityInstanceProvider {Container = unity};
}
public void ApplyDispatchBehavior(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach (var ed in
serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>().SelectMany(cd => cd.Endpoints))
{
InstanceProvider.ServiceType = serviceDescription.ServiceType;
ed.DispatchRuntime.InstanceProvider = InstanceProvider;
}
}
public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters) { }
public void Validate(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase) { }
public void AddToHost(ServiceHost host)
{
if (_serviceHost != null)
return;
host.Description.Behaviors.Add(this);
_serviceHost = host;
}
}
}
UnityInstanceProvider, a WCF Service Instance provider:
using System;
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.Practices.Unity;
namespace Services.Host.Infrastructure
{
public class UnityInstanceProvider : IInstanceProvider
{
public IUnityContainer Container { set; get; }
public Type ServiceType { set; get; }
public UnityInstanceProvider() : this(null) { }
public UnityInstanceProvider(Type type)
{
ServiceType = type;
Container = new UnityContainer();
}
public object GetInstance(
InstanceContext instanceContext,
Message message)
{
return Container.Resolve(ServiceType);
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
}
DefaultHostFactory that will take a Unity Configuration class as an argument (A class where all type is registered to the Unity Container):
using DependencyConfiguration;
using Services.Host.Infrastructure;
namespace HostFactory
{
public class DefaultHostFactory : UnityServiceHostFactory
{
public DefaultHostFactory() : base(new WcfUnityConfiguration())
{
}
}
}
Make sure to set the new Host Factory in the .svc file:
<%@ ServiceHost Language="C#" Factory="HostFactory.DefaultHostFactory"
Service="MyService, MyServices" %>
Unity, a helper class to Configure the Unity Container and also can be used to Resolve a type:
using System;
using Microsoft.Practices.Unity;
namespace Infrastructure.IocContainer
{
public static class Unity
{
private static IUnityContainer _container;
private static object _lock = new object();
public static void Configure(IUnityConfiguration configuration)
{
if (configuration == null)
throw new ArgumentNullException("configuration");
lock (_lock)
{
if (_container != null)
return;
_container = new UnityContainer();
configuration.Configure(_container);
}
}
public static T Resolve<T>()
{
return Current.Resolve<T>();
}
public static IUnityContainer Current
{
get
{
if (_container == null)
throw new ApplicationException("You have to Configure the Unity first, you can do that by calling the Configure method");
return _container;
}
}
}
}
IUnityConfiguration:
using Microsoft.Practices.Unity;
namespace Infrastructure.IocContainer
{
public interface IUnityConfiguration
{
void Configure(IUnityContainer container);
}
}
WcfUnityConfiguration, a separate class to put all registration of types into the Unity container:
using Infrastructure.IocContainer;
using Microsoft.Practices.Unity;
namespace DependencyConfiguration
{
public class WcfUnityConfiguration : IUnityConfiguration
{
public void Configure(IUnityContainer container)
{
container.RegisterType<IFoo, Foo>();
//...
}
}
}
Fork
0 Feedback
You must log in before you can give any feedback
0
I found this useful, but I found that if my service implements IDisposable, the Dispose method isn't getting called.
UnityInstanceProvider.ReleaseInstance should probably check if the instance object is IDisposable and call Dispose?
thanks!
0
Thanks for a great article. I have implemented in a WCF service hosted in IIS.
I have one problem, the DefaultHostFactory is not called 'prior' to the WCF service constructor which is what I need in order to be able to . I am trying to use Enterprise Library's Unity Dependency injection to to resolve two dependencies passed in to the constructor. Strangely, if I use only one of the parameters, the dependency is resolved (even though the DefaultHostFactory is not called). It fails when I try with two parametes.
The concrete class implementing IInstanceProvider is called prior to the constructor running.
Is there something in the config file that I need to add to ensure that the DefaultHostFactory is instantiated and then the IUnityConfiguration.Configure method is called.
I have configured it as per your example in the svc file. I am using Enterprise Library 5.0; .Net framework 4.0
Thanks again.
Regards
Grant
You must log in before you can post a comment


2.67k
0


Mark '.net4' tag as 'like'
Mark '.net4' tag as 'ignore'