This project is read-only.

Basic WCF Client Injection Tutorial

This tutorial aims to illustrate the usage of the WCF Client Injection extension to Unity 1.2 that can be found in the DigitallyCreated.Utilities.Unity assembly. It expects you to know C#, WCF and Unity.

The purpose of the WCF Client Injection extension to Unity is to allow you to easily get Unity to inject a WCF proxy when you ask for a concrete instance of the service interface. For example, if you had the following interface...

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    int GetRandomNumber(int maxLimit);
}

...you could get Unity to inject a WCF proxy to the WCF service that runs a service by that contract by simply going:

IMyService myService = myUnityContainer.Resolve<IMyService>();

And the beauty is that you could then get Unity to inject any other concrete class that implements IMyService there too, just by changing the configuration. So maybe that same Resolve call above would return this concrete class instead of a WCF proxy:

public class MyService : IMyService
{
    public int GetRandomNumber(int maxLimit)
    {
        Random random = new Random();
        return random.Next(maxLimit);
    }
}

So how do we set this WCF client injection up to happen in Unity?

XML Configuration

The best, easiest and most configurable way to set up WCF proxy injection is a little configuration in your Unity XML configuration:

<unity>
    <containers>

        <container>

            <extensions>
                <add type="DigitallyCreated.Utilities.Unity.WcfProxyContainerExtension, DigitallyCreated.Utilities.Unity" />
            </extensions>

            <extensionConfig>

                <add name="WcfProxyContainerExtensionConfig"
                     type="DigitallyCreated.Utilities.Unity.Configuration.WcfProxyExtensionConfigurationElement, DigitallyCreated.Utilities.Unity">
                    <serviceInterfaces>

                        <serviceInterface type="MyServices.IMyService, MyServicesAssembly"
                                          endpointConfiguration="MyServiceEndpoint" />

                    </serviceInterfaces>
                </add>

            </extensionConfig>
        </container>

    </containers>
</unity>

Let's step through that blast of XML piece by piece. In the extensions element we're telling Unity about this extension to its default functionality. Then, in extensionConfig (which is where Unity lets extensions configure themselves) we're declaring a new configuration with the add tag. The name specified there is arbitrary. The type specified is the .NET class that the .NET Configuration system (System.Configuration) will use to deserialize the configuration (in this case, the extension's class).
The serviceInterfaces element inside the add gives us a place to start declaring our service interfaces (using serviceInterface elements). For this example, we're declaring that we want Unity to give us a WCF proxy when we ask for the IMyService interface. We also say that we want that service client proxy class to be configured with the settings defined in the "MyServiceEndpoint" configuration that we've defined elsewhere in our XML configuration (a standard part of WCF service client configuration; done inside the familiar system.ServiceModel tag).

If you'd like to be able to register the WCF interface with Unity with a certain name so that you can do this...

IMyService myService = myUnityContainer.Resolve<IMyService>("MyMappingName");

... you can. Simply change the serviceInterface declaration to be this:

<serviceInterface type="MyServices.IMyService, MyServicesAssembly"
                  name="MyMappingName"
                  endpointConfiguration="MyServiceEndpoint" />

Note the inclusion of the name attribute.

Gotchas

WCF clients are IDisposable and should disposed when you're finished with them. But if Unity just gives you an IMyServiceInterface, how are you to know whether it's a WCF service client, or something else (you're not supposed to know, this is dependency injection). The easiest way to deal with this is to use some smart disposer code like this:

/// <summary>
/// The SmartDisposer class is a utility class that contains a method that implements
/// disposing functionality
/// </summary>
public static class SmartDisposer
{
    /// <summary>
    /// This method disposes an object if it is <see cref="IDisposable"/> and if it is safe to do so
    /// </summary>
    /// <remarks>
    /// The method will not dispose the object if it is a WCF client that is faulted, since that
    /// will cause an exception to be thrown.
    /// </remarks>
    /// <param name="obj">The object to dispose</param>
    public static void Dispose(object obj)
    {
        IDisposable disposable = obj as IDisposable;
        if (disposable != null)
        {
            //If its a WCF client, don't try to dispose of it if its faulted or else you'll cause
            //an exception that'll suppress the display of exception that caused the fault in the 
            //first place
            if (obj is ICommunicationObject && ((ICommunicationObject)obj).State == CommunicationState.Faulted)
                return;

            disposable.Dispose();
        }
    }
}

So when you're done with your IMyService, run SmartDisposer.Dispose on it. If it's a WCF client, it'll be disposed safely, if not, it won't be disposed at all, which keeps the rest of your code oblivious to what IMyService really is.

Last edited Mar 22, 2010 at 8:28 AM by dchambers, version 2

Comments

No comments yet.