Unity: The Static Factory Extension

On June 15, 2009, in Uncategorized, by derekgreer

The Unity Inversion of Control container comes with an extension called the StaticFactoryExtension. The purpose of this extension is to add the ability to register types within the container while deferring the instantiation of the type to a factory method. This enables a number of scenarios where finer-grained control over the construction of an object is desired.

As the name suggests, one example use of the extension is with a static factory method. In the following test, an ILoggingService is registered with the container by configuring it to call the LoggingService.GetLoggingService() static method via the IStaticFactoryConfiguration.

namespace StaticFactoryExample
{
    public class StaticFactoryExampleSpecs
    {
        [TestFixture]
        public class When_a_logging_service_is_resolved_using_a_static_factory_method
        {
            UnityContainer _container;

            [SetUp]
            public void SetUp()
            {
                _container = new UnityContainer();

                _container
                    .AddNewExtension()
                    .Configure()
                    .RegisterFactory(container =>
                                     LoggingService.GetLoggingService());
            }

            [Test]
            public void A_logging_service_should_be_returned()
            {
                Assert.IsNotNull(_container.Resolve());
            }
        }
    }

    public interface ILoggingService
    {
    }

    public sealed class LoggingService : ILoggingService
    {
        readonly Log4NetLogger _logger;

        LoggingService(Log4NetLogger logger)
        {
            _logger = logger;
        }

        public static ILoggingService GetLoggingService()
        {
            return Nested.instance;
        }

        static class Nested
        {
            internal static readonly ILoggingService instance = new LoggingService(new Log4NetLogger());
        }
    }

    public interface ILogger
    {
    }

    public class Log4NetLogger : ILogger
    {
    }
}

While use with actual static factory methods may have been the driving factor for the creation of this extension, there is nothing inherently prescriptive about the extension which necessitates that the methods used be static.

Another example use of the StaticFactoryExtension is to conceal dependencies of resolved types which you may not want to be accessible through the container. Consider the following alternate example registration of the ILoggingService:

namespace StaticFactoryExample
{
    public class StaticFactoryExampleSpecs
    {
        [TestFixture]
        public class When_a_logging_service_is_resolved_using_a_static_factory_method
        {
            UnityContainer _container;

            [SetUp]
            public void SetUp()
            {
                _container = new UnityContainer();

                _container
                    .AddNewExtension()
                    .RegisterType(new ContainerControlledLifetimeManager())
                    .Configure()
                    .RegisterFactory(container =>
                                     new LoggingService(new Log4NetLogger()));
            }

            [Test]
            public void A_logging_service_should_be_returned()
            {
                Assert.IsNotNull(_container.Resolve());
            }

            [Test]
            public void The_logging_service_returned_should_always_be_the_same_instance()
            {
                Assert.AreSame(
                    _container.Resolve(),
                    _container.Resolve());
            }
        }
    }

    public interface ILoggingService
    {
    }

    public class LoggingService : ILoggingService
    {
        readonly ILogger _logger;

        public LoggingService(ILogger logger)
        {
            _logger = logger;
        }
    }

    public interface ILogger
    {
    }

    public class Log4NetLogger : ILogger
    {
    }
}

In this example, the LoggingService is implemented as a class with an ILogger dependency which must be supplied through the constructor. The factory method responsible for returning the ILoggingService has been rewritten as an expression which returns a newly instantiated instance of the LoggingService and supplies an instance of Log4NetLogger as its dependency implementation. Additionally, the ILoggingService has been registered with a ContainerControlledLifetimeManager. A lifetime manager within Unity is a type responsible for governing how instances of types registered with the container are managed. The ContainerControlledLifetimeManager holds a single instance of the registered type once created and returns the same instance upon all requests. This effectively causes the container to manage the instance as a singleton without placing this responsibility upon the class itself, and without otherwise incurring the drawbacks that the singleton design pattern imposes upon a class.

While enabling the ILoggingService to be resolved by the container could have been achieved without the use of the StaticFactoryExtension by simply registering the LoggingService implementation and the ILogger dependency type, this would have made the instance of ILogger available to types within the system which may not be desired. In this case, the ILoggingService is intended as the public API to be used by types within the system for logging needs. The ILogger type is simply a strategy for how this is accomplished. This approach enables the ILoggingService to be lazy-loaded by the container without exposing the ILogger type.

While the StaticFactoryExtension provides useful behavior to the Unity container, one might argue that the API leaves something to be desired. One of the strengths of the Unity container is its extensibility model. In fact, all of Unity’s functionally is facilitated through extensions. Unfortunately, this means additional functionality such as that provided by the StaticFactoryExtension requires calling the Configure
() method to obtain a reference to the extension. The result is that some degree of ceremony is required each time a factory method needs to be registered for a type.

One approach to improving the API is to encapsulate the required calls to configure a factory method within an extension method. Consider the following extension methods:

    public static class UnityExtensions
    {
        public static IUnityContainer RegisterType(this IUnityContainer container, FactoryDelegate factoryMethod)
        {
            container.Configure().RegisterFactory(factoryMethod);
            return container;
        }

        public static IUnityContainer RegisterType(this IUnityContainer container, FactoryDelegate factoryMethod,
                                                   LifetimeManager lifetimeManager)
        {
            container
                .RegisterType(lifetimeManager)
                .Configure().RegisterFactory(factoryMethod);
            return container;
        }
    }

In the case of the eariler ILoggingService example, where the desired behavior is to always return the same instance, using the extension method which accepts a FactoryDelegate and a LifetimeManager allows the StaticFactoryExtension behavior to be used as follows:

        [SetUp]
        public void SetUp()
        {
            _container = new UnityContainer();

            _container
                .AddNewExtension()
                .RegisterType(container => new LoggingService(new Log4NetLogger()),
                              new ContainerControlledLifetimeManager());
        }
Tagged with:  

Inspired by Jeremy Miller’s presentation of StructureMap’s convention-based type registration at this week’s Austin .Net User’s Group, I set out to create a convention-based type registration extension for the Unity container.

For those unfamiliar with the convention-based approach to type registration for IoC containers, I’ll refer you to Jeremy’s article here which should get you up to speed on the concept.

Unity is fairly easy to extend, so I had the first working prototype after about 15 minutes. I spent several hours afterward, however, trying to tease out an API I felt was suitable. After a few cycles attempting to design a fluent API, I settled upon something similar to Fluent NHibernate’s mapping registration, and one which I think fits decently with Unity’s existing API.

Without further ado, here is an example of its usage:

        [Concern("During setup")]
        public class When_container_configured_with_interface_impl_name_match_convention :
            Behaves_like_context_with_container_with_convention_extension
        {
            protected override void Because()
            {
                _container
                    .Using<IConventionExtension>()
                    .Configure(x =>
                        {
                            x.Conventions.Add<InterfaceImplementionNameMatchConvention>();
                            x.Assemblies.Add(Assembly.GetExecutingAssembly());
                        })
                    .Register();
            }

            [Observation, Test]
            public void Types_matching_convention_should_be_auto_registered()
            {
                _container.Resolve<ITestType>().ShouldBeOfType(typeof (TestType));
            }
        }

After adding the extension to the container, the IConventionExtension configuration is used to configure the conventions and assemblies used during the auto-registration process. The convention used here matches the common .Net naming convention where interface and default implementation pairs share the same name, with the interface carrying an ‘I’ prefix. The test demonstrates resolving an instance of ITestType, though no explicit registration has been provided.

The following test demonstrates using an alternate convention where only implementations of the specified type are auto-registered:

        [Concern("During setup")]
        public class When_container_configured_with_implementation_convention_with_name_replacement :
            Behaves_like_context_with_container_with_convention_extension
        {
            protected override void Because()
            {
                _container
                    .Using<IConventionExtension>()
                    .Configure(x =>
                        {
                            x.Conventions.Add<ImplementationConvention<IController>>();
                            x.Assemblies.Add(Assembly.GetExecutingAssembly());
                        })
                    .Register(x => x.Replace("Controller", ""));
            }

            [Observation, Test]
            public void Controller_types_should_be_resolvable_by_prefix_name()
            {
                _container.Resolve<IController>("MainView").ShouldNotBeNull();
            }

            [Observation, Test]
            public void Types_not_of_type_controller_should_not_be_resolvable()
            {
                try
                {
                    _container.Resolve<ITestType>();
                    throw new Exception("Type ITestType should not be resolvable.");
                }
                catch (ResolutionFailedException)
                {
                }
            }
        }

In this example, the types are registered by name utilizing a delegate to facilitate the ability to modify the default name of the concrete type to be registered in some way. In this case, all implementations of IController are registered under the name of the concrete type, minus the “Controller” suffix.

The full extension source can be downloaded at: http://code.google.com/p/conventionextension/. Enjoy!

Inspired by Sebastien Lambla’s post, Implementing INotifyPropertyChanged with DynamicProxy2, I decided to provide an example of how INotifyPropertyChanged can be implemented using Unity’s new interception capabilities.

Prolegomena

While not necessary for using the Unity container, some may find a basic understanding of how Unity works to be helpful when registering objects for interception or using other capabilities of Unity.

The Unity container is best understood as a façade for a highly configurable, yet complex object factory named Object Builder. Object Builder made its debut within the Composite UI Application Block in November 2005 and was subsequently incorporated into Enterprise Library 2.0 with its January 2006 release as its internal configuration strategy.

At its core, Object Builder is based upon the Chain-of-Responsibility pattern. The Object Builder chain-of-responsibility utilizes two primary concepts for configuring how objects are constructed: namely, Strategies and Policies. Strategies serve as the concrete handlers within the chain-of-responsibility implementation, and are the objects which encapsulate the behavior performed during the construction process. Policies serve as the rules for how and when Strategies apply to a given type. Strategies and Policies are the essence of Object Builder’s extensibility, and by extension Unity’s extensibility.

While Object Builder can be used directly to provide advanced dependency injection and other inversion of control needs, due to the fact that it waswritten to serve the internal needs of the guidance assets provided by the Microsoft Patterns & Practices group, it wasn’t developed with ease of use in mind and didn’t provide the same API nomenclature used by other containers. This is where Unity comes in.

Unity was written to provide an easy to use and more traditional container interface to Object Builder. Part of this interface includes a more simplified end-user extensibility API in the form of Unity Extensions. These extensions encapsulate the lower-level Strategy and Policy configuration for Object Builder.

The 1.2 release of Unity in October 2008 included a new extension for facilitating aspect-oriented programming through method interception. The remainder of this article demonstrates how this new extension can be used to implement the INotifyPropertyChanged interface.

Interception Example

To start, we’ll create a test fixture skeleton to drive our example:

[TestFixture]
public class When_model_property_changes
{
    [SetUp]
    public void SetUp()
    {
        EstablishContext();
        Because();
    }

    protected override void EstablishContext()
    {
    }

    protected override void Because()
    {
    }

    [Test]
    public void A_notify_property_changed_event_should_be_raised()
    {
    }
}

Next, we’ll establish the context of our test by configuring an instance of the Unity container to intercept methods for a type named IModel:

[TestFixture]
public class When_model_property_changes : ContextSpecification
{
    IUnityContainer container;
    IModel model;

    /** snip **/

    protected void EstablishContext()
    {
        container = new UnityContainer();

        container.AddNewExtension()
        .RegisterType<IModel, Model>()
        .Configure()
        .SetDefaultInterceptorFor<IModel>(new TransparentProxyInterceptor());

        model = container.Resolve<IModel>();
    }

    /** snip **/
}

We configure our container by first adding the Interception extension. Next, we register the type we will be resolving from the container. Finally, we set a default interceptor for our type.

By adding the Interception extension, two new build strategies are added to the chain-of-responsibility for facilitating interception. Additionally, the extension registers an instance of an AttributeDrivenPolicy which is used by the interception strategies to provide the ability to identify which methods should be intercepted through the use of attributes. We will later create a custom attribute derived from HandlerAttribute which will match our type with the AttributeDrivenPolicy.

Note: The AttributeDrivenPolicy is a policy type internal to the Interception extension and is not related to the IBuilderPolicy types used by the Object Builder component.

Our last step in establishing the context for our test is to have the container create an instance of our registered type.

Next, we’ll define the behavior of our test to be observed:

protected override void Because()
{
    model.PropertyChanged += (sender, args) => { propertyChangedEventRaised = true; };
    model.TestProperty = "[any value]";
}

Here, we establish that the model should have a public event named PropertyChanged and a public writable string member named TestProperty. When the event is fired, we’ll set a Boolean named propertyChangedEventRaised to true which we’ll test for later in our observation.

Our next step is to go ahead and create the types we’ve registered with the container and declare our propertyChangedEventRaised Boolean member:

[TestFixture]
public class When_model_property_changes
{
    IUnityContainer container;
    IModel model;
    bool propertyChangedEventRaised;

    internal interface IModel : INotifyPropertyChanged
    {
        string TestProperty { get; set; }
    }

    internal class Model : IModel
    {
        public string TestProperty { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;
    }

    /** snip **/
}

Notice that we currently have no code within the Model type to actually raise the PropertyChanged event.

Next, we need to provide the observation portion of our test:

bool propertyChangedEventRaised;

[Test]
public void Should_raise_notify_property_changed_event()
{
    Assert.That(propertyChangedEventRaised, Is.True);
}

Running the test at this point produces the expected failure result:

To make the test pass, we need to configure our type to match an interception policy and provide an interception handler which will raise the

PropertyChanged event on behalf of our type. Since we’re using the default AttributeDrivenPolicy to have the interception strategies recognize our type as one to be intercepted, we need to create an attribute derived from the extension’s HandlerAttribute:

/// <summary>
/// This attribute is used to denote that the event is to be intercepted.
/// </summary>
public class NotifyAttribute : HandlerAttribute
{
    readonly ICallHandler handler;

    public NotifyAttribute()
    {
        handler = new NotifyPropertyChangedCallHandler();
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return handler;
    }
}

The HandlerAttribute is used by the AttributeDrivenPolicy to return an ICallHandler. The ICallHandler type encapsulates the behavior used to intercept method calls for the configured types within Unity. Here, we return a NotifyPropertyChangedCallHandler() which will intercept all call to methods adorned with our custom attribute.

Next, we create our NotifyPropertyChangedCallHandler to raise the PropertyChanged event for our property:

/// <summary>
/// This class handler is used in conjunction with Unity to handle INotifiyPropertyChanged
/// implementations as an aspect.
/// </summary>
class NotifyPropertyChangedCallHandler : ICallHandler
{
    public int Order
    {
        get { return 0; }
        set { }
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        IMethodReturn result = getNext.Invoke().Invoke(input, getNext);
        MethodBase method = input.MethodBase;

        if (method.IsSpecialName && method.Name.StartsWith("set_"))
        {
            // Get the property name
            string propertyName = method.Name.Substring(4);

            // Get the private event backing field
            FieldInfo info = input.Target.GetType()
            .GetFields(BindingFlags.InstanceBindingFlags.NonPublic)
            .Where(f => f.FieldType == typeof (PropertyChangedEventHandler))
            .FirstOrDefault();

            if (info != null)
            {
                var handler = info.GetValue(input.Target) as PropertyChangedEventHandler;

                // Ensure subscriptions
                if (handler != null)
                {
                    handler.Invoke(input.Target, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

        return result;
    }
}

Finally, we need to add our custom attribute to the property of our type for which we want our interception to occur:

internal class Model : IModel
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string TestProperty { get; [Notify] set; }
}

Running our test again shows that it now passes!

Tagged with: