Tuesday, November 05, 2013

Building Unity.WebForms (Part 3 of 4)

Registering your types in the container

Now that all of the plumbing has been taken care of, we need a way to register our types so that they can be injected into our pages and controls.

When you install the Unity.WebForms NuGet package, a new folder will be added to your project called 'App_Start' with a class named UnityWebFormsStart.cs. If you have already added another NuGet package that also makes use of the WebActivator package by David Ebbo, then this folder may have already been created.

The PostStart method is tasked with creating the parent instance of the Unity container, adding it to the Application state cache, and calling the RegsiterDependencies helper method. There is no need to modify this portion of the code unless you need to do something different when initializing the container (such as when using other blocks in the Enterprise Library, in which case you would need to ensure that the container reads the configuration information from web.config).

The RegisterDependencies method is where you will register any types/services that you want to have injected into your pages, controls, and types at runtime.

Included in this source repository is a sample ASP.NET 4.0 Web Application that uses the latest Unity.WebForms NuGet package. The contents of its RegisterDependencies method is a follows:

private static void RegisterDependencies( IUnityContainer container )
{
container
// registers Service1 as '1 instance per child container' (new object for each request)
.RegisterType<Service1, Service1>( new HierarchicalLifetimeManager() )
// registers Service2 as 'new instance per resolution' (each call to resolve = new object)
.RegisterType<Service2, Service2>();
}

This uses the fluent interface (method chaining) of the container to register two types: Service1 and Service2. The registration of Service1 uses the Hierarchical Lifetime Manager to ensure that each child container gets it's own instance of the service. This is critical when using a type like an Entity Framework context to ensure that all database operations for a single user (updates and deletes in particular) are isolated from other users. The registration of Service2 doesn't define a Lifetime Manager, so it gets the default behavior of 'per-call', which means each time the container is asked for an instance of Service2 it will create a brand new object.


The last bit of magic that allows this class to be run just after the application has been started, but before requests are processed, is the assembly directive just before the namespace declaration:

[assembly: WebActivator.PostApplicationStartMethod( typeof(SampleWebApplication.App_Start.UnityWebFormsStart), "PostStart" )]

This functions very similarly to the way the UnityHttpModule module gets registered, but is using the WebActivator library that adds the ability to have multiple code classes before and after the application has been started.

Recap


Registering your types for injection has been made fairly simple, thanks to the WebActivator library. This can be made even simpler using reflection if you have an assembly that contains all of your services or are using a common interface. Either way, the most important part of registering your types for injection is to ensure you are using the proper lifetime manager for them. Some of the harder bugs I have had to track down have been because the wrong lifetime manager was used and I was either getting a new object each time (and losing state) or getting the same object every time (and getting cached/stale data).


In the last part of this series, we will tie everything together and see a working example.