In one of my previous posts I demonstrated how you can build a Castle Windsor facility to create WCF Proxy classes given the interface of the service (Castle Windsor WCF Services Resolution Facility). For my WPF/Silverlight application framework I needed the same feature for the IoC container I’m using there, so here it is how you can implement the same functionality in Unity.

The extension points in Unity are very different from Castle Winsor, what we have to do to implement our WCF proxy class generator through resolution is to create the following classes:

  • WcfProxyBuildPlanPolicy: a BuildPlan policy that will be used by the engine to create the instances of the proxy classes.
  • IWcfProxyConfiguration: an interface used to register the new types in the IoC container and associated them with the buildplan policy used to construct the instances of the objects.
  • WcfProxyUnityContainerExtension: a container Extension that will expose the concrete implementation of the methods of the IWcfProxyConfiguration interface.

Here’s the first implementation of those classes:

/// <summary>
/// policy used to build the wcf proxy from the interface and the endpoint configuration passed in
/// </summary>
public class WcfProxyBuildPlanPolicy : IBuildPlanPolicy
{
 
    public WcfProxyBuildPlanPolicy(string endpointConfiguration)
    {
        EndpointConfiguration = endpointConfiguration;
    }
 
    public string EndpointConfiguration { get; set; }
 
    #region IBuildPlanPolicy Members
 
    public void BuildUp(IBuilderContext context)
    {
        if (context.Existing == null)
        {
            Type typeToConstruct = BuildKey.GetType(context.BuildKey);
            context.Existing = CreateWcfChannelProxy(typeToConstruct, EndpointConfiguration);
        }
    }
 
    #endregion
 
    /// <summary>
    /// create a wcf channel through reflection
    /// </summary>
    /// <param name="service"></param>
    /// <param name="endpoint"></param>
    /// <returns></returns>
    public static object CreateWcfChannelProxy(Type service, string endpoint)
    {
        Type channelFactoryBaseType = typeof(ChannelFactory<>);
        channelFactoryBaseType = channelFactoryBaseType.MakeGenericType(service);
        // Create an instance
        object instance = Activator.CreateInstance(channelFactoryBaseType, endpoint);
        MethodInfo createchannel = instance.GetType().GetMethod("CreateChannel", new Type[0]);
        return createchannel.Invoke(instance, null);
    }
}

/// <summary>
/// configuration interface exposed by the Wcf Proxy extension, it will be used to register new types in the container
/// </summary>
public interface IWcfProxyConfiguration : IUnityContainerExtensionConfigurator
{
    IUnityContainerExtensionConfigurator RegisterType<TTypeToBuild>(string endpointconfiguration);
 
    IUnityContainerExtensionConfigurator RegisterType<TTypeToBuild>(string name, string endpointconfiguration);
}

/// <summary>
/// Container extension class, it's used to allow access to the new WcfProxyBuildPlanPolicy, it allow to associate an interface type
/// with the new creation policy.
/// </summary>
/// <remarks>
/// usage is like:
/// container.AddNewExtension<WcfProxyUnityContainerExtension>();
/// container.Configure<IWcfProxyConfiguration>().RegisterType<TTypeToBuild>(string endpointconfiguration);
/// TTypeToBuild service = container.Resolve<TTypeToBuild>();
/// </remarks>
public class WcfProxyUnityContainerExtension : UnityContainerExtension, IWcfProxyConfiguration
{
    protected override void Initialize()
    {
    }
 
    #region IWcfProxyConfiguration Members
 
    /// <summary>
    /// registers an interface to be used with the Wcf Proxy creation policy, a wcf proxy will be created for the interface passed in
    /// </summary>
    /// <typeparam name="TTypeToBuild">Interface to register</typeparam>
    /// <param name="name">name</param>
    /// <param name="endpointconfiguration">wcf end point configuration</param>
    /// <returns></returns>
    public IUnityContainerExtensionConfigurator RegisterType<TTypeToBuild>(string name, string endpointconfiguration)
    {
        WcfProxyBuildPlanPolicy policy = new WcfProxyBuildPlanPolicy(endpointconfiguration);
        Context.Policies.Set<IBuildPlanPolicy>(policy, NamedTypeBuildKey.Make<TTypeToBuild>(name));
        return this;
    }
 
    public IUnityContainerExtensionConfigurator RegisterType<TTypeToBuild>(string endpointconfiguration)
    {
        return RegisterType<TTypeToBuild>(null, endpointconfiguration);
    }
    
    #endregion
}

To use those extensions you need to use a code like this:

   1: [TestMethod]
   2: public void T02WindsorFacilityTest()
   3: {
   4:     UnityContainer container = new UnityContainer();
   5:     container.AddNewExtension<WcfProxyUnityContainerExtension>();
   6:     container.Configure<IWcfProxyConfiguration>().RegisterType<ITestService>("BasicHttpBinding_ITestService");
   7:     ITestService test = container.Resolve<ITestService>();
   8:     Assert.IsNotNull(test);
   9:     Assert.IsInstanceOfType(test, typeof(ITestService));
  10: }

With line 5 you add the extension to the container.

With line 6 you ask the container for the configuration interface exposed by the extension and you use it to associate the ITestService interface with the WCF proxy generation buildplan (passing in the configuration for the WCF end-point).

Update: for a good introduction at ObjectBuilder and Unity dependency injection system you can look at this blog post: Deconstructing ObjectBuilder - What Is ObjectBuilder? some classes are a little different in the actual ObjectBuilder implementation, nonetheless it gave a good picture of how the things work.

Related Content