Extending and Demonstrating the Type Tracking Extension for Unity

Recently, I have received a few requests for some changes and an example for my Type Tracking Extension for Unity. This post is to address those requests. Of course, all of the source code for this post is added to the GitHub project Unity Extensions.

Part One – Extension Methods for the Type Tracking Extension

The number one request I have received, and my own number one issue with using the Type Tracking Extension, is the verbosity of each method call. Here is a typical method call.

container.Configure().TryResolve();

This is the typical extension usage model for Unity. Besides the verbosity, it implies that I am configuring the extension, when I am just trying to use it. I try to avoid code that implies something other than what I intend, so this syntax bothers me.

To address this issue, I have added a new class of extension methods to the Type Tracking project. Here is the source code.

namespace hazware.unity.extensions { /// /// Extension methods to simplify using the TypeTrackingExtension for Unity. /// Requires .NET 3.5 /// public static class UnityExtensions { #region CanResolve /// /// Determines whether this type can be resolved as the default. /// /// The type to test for resolution /// The unity container. /// /// true if this instance can resolve; otherwise, false. /// public static bool CanResolve(this IUnityContainer container) { return container.Configure().CanResolve(); } /// /// Determines whether this type can be resolved with the specified name. /// /// The type to test for resolution /// The unity container. /// The name associated with the type. /// /// true if this instance can resolve; otherwise, false. /// public static bool CanResolve(this IUnityContainer container, string name) { return container.Configure().CanResolve(name); } /// /// Determines whether this instance can be resolved at all with or without a name. /// /// The type to test for resolution /// The unity container. /// /// true if this instance can resolve; otherwise, false. /// public static bool CanResolveAny(this IUnityContainer container) { return container.Configure().CanResolveAny(); } #endregion #region TryResolve /// /// Tries to resolve the type, returning null if not found. /// /// The type to try and resolve /// The unity container. /// The unity container. /// An object of type if found, or null if not. /// The unity container. public static T TryResolve(this IUnityContainer container) { return container.Configure().TryResolve(); } /// /// Tries to resolve the type with the specified of name, returning null if not found. /// /// The type to try and resolve /// The unity container. /// The name associated with the type. /// An object of type if found, or null if not. public static T TryResolve(this IUnityContainer container, string name) { return container.Configure().TryResolve(name); } /// /// Tries to resolve the type, returning the passed in defaultValue if not found. /// /// The type to try and resolve /// The unity container. /// The default value. /// An object of type if found, or the if not. public static T TryResolve(this IUnityContainer container, T defaultValue) { return container.Configure().TryResolve(defaultValue); } /// /// Tries to resolve the type, returning the passed in defaultValue if not found. /// /// The type to try and resolve /// The unity container. /// The name associated with the type. /// The default value. /// An object of type if found, or the if not. public static T TryResolve(this IUnityContainer container, string name, T defaultValue) { return container.Configure().TryResolve(name, defaultValue); } #endregion #region ResolveAll /// /// Resolves all elements of a type, including the default. /// /// The type to resolve /// The unity container. /// of T public static IEnumerable ResolveAllToEnumerable(this IUnityContainer container) { return container.Configure().ResolveAll(); } /// /// Resolves all registered T in the container, conditionally including the default unnamed /// registered T. When includeDefault is false, this is the same as the normal Unity /// ResolveAll. /// /// The type to resolve /// The unity container. /// if set to true include default value, else do not include default. /// of T public static IEnumerable ResolveAllToEnumerable(this IUnityContainer container, bool includeDefault) { return container.Configure().ResolveAll(includeDefault); } /// /// Resolves all elements of a type, including the default, and returns /// as an array of T. /// /// The type to resolve /// The unity container. /// Array of T public static T[] ResolveAllToArray(this IUnityContainer container) { return container.Configure().ResolveAllToArray(); } /// /// Resolves all registered T in the container, conditionally including the default unnamed /// registered T. When includeDefault is false, this is the same as the normal Unity /// ResolveAll. /// /// The type to resolve /// The unity container. /// if set to true include default value, else do not include default. /// Array of T public static T[] ResolveAllToArray(this IUnityContainer container, bool includeDefault) { return container.Configure().ResolveAllToArray(includeDefault); } #endregion } }

Using these extension methods makes the above sample code look like this:

container.TryResolve();

This is more concise, and more importantly, clearly states the meaning of the code. However, the catch for this syntactic sugar is that it uses extension methods. That means that .NET 3.5 is now a requirement for the Type Tracking Extension.

Part Two – Type Tracking Usage Sample{:.float_right}

I have received a few requests for a simple example of how to use the Type Tracking Extension. So here it is.

Step 1 – Add a reference to the hazware.unity.extensions assembly into your project.

Step 2 – Add the following using statement to your source file:

using hazware.unity.extensions;

Step 3 – Register the extension with the Unity container. Here is some sample code:

IUnityContainer container = new UnityContainer(); container.AddNewExtension();

Step 4 – Use the extension. Here some more sample code:

Console.WriteLine("CanResolve() == {0}", container.CanResolve()); Console.WriteLine("CanResolve() == {0}", container.CanResolve());

That’s it. So here is a complete sample program.

class Program { static void Main(string[] args) { IUnityContainer container = new UnityContainer(); container.AddNewExtension(); container.RegisterType(); container.RegisterType("Named"); Console.WriteLine("CanResolve() == {0}", container.CanResolve()); Console.WriteLine("CanResolve(\"Named\") == {0}", container.CanResolve("Named")); Console.WriteLine("CanResolve() == {0}", container.CanResolve()); Console.WriteLine("TryResolve() == null ==> {0}", container.TryResolve() == null); Console.WriteLine("TryResolve(\"Named\") == null ==> {0}", container.TryResolve("Named") == null); Console.WriteLine("TryResolve() == null ==> {0}", container.TryResolve() == null); Console.WriteLine("TryResolve(new ABar()) == null ==> {0}", container.TryResolve(new ABar()) == null); Console.WriteLine("TryResolve(\"Named\", new ABar()) == null ==> {0}", container.TryResolve("Named", new ABar()) == null); Console.WriteLine("ResolveAllToEnumerable().Count() == {0}", container.ResolveAllToEnumerable().Count()); Console.WriteLine("ResolveAllToEnumerable(false).Count() == {0}", container.ResolveAllToEnumerable(false).Count()); Console.WriteLine("ResolveAllToEnumerable().Count() == {0}", container.ResolveAllToEnumerable().Count()); Console.WriteLine("ResolveAllToArray().Length == {0}", container.ResolveAllToArray().Length); Console.WriteLine("ResolveAllToArray(false).Length == {0}", container.ResolveAllToArray(false).Length); Console.WriteLine("ResolveAllToArray().Length == {0}", container.ResolveAllToArray().Length); } }

This source is in the SampleApp project checked into the Unity Extensions project up on GitHub.

Hopefully, the extension methods make using the Type Tracking Extension easier to use, and the sample helps to demonstrates its usage.