•  
  • Programming
  • Extending and Demonstrating the Type Tracking Extension for Unity

Extending and Demonstrating the Type Tracking Extension for Unity

Categories: Programming
Comments: 14 Comments
Published on: August 20, 2009

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.

   1: container.Configure<TypeTrackingExtension>().TryResolve<ITest>();

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.

   1: namespace hazware.unity.extensions

   2: {

   3:   /// <summary>

   4:   /// Extension methods to simplify using the TypeTrackingExtension for Unity.

   5:   /// Requires .NET 3.5

   6:   /// </summary>

   7:   public static class UnityExtensions

   8:   {

   9:     #region CanResolve

  10:     /// <summary>

  11:     /// Determines whether this type can be resolved as the default.

  12:     /// </summary>

  13:     /// <typeparam name="T">The type to test for resolution</typeparam>

  14:     /// <param name="container">The unity container.</param>

  15:     /// <returns>

  16:     ///     <c>true</c> if this instance can resolve; otherwise, <c>false</c>.

  17:     /// </returns>

  18:     public static bool CanResolve<T>(this IUnityContainer container)

  19:     {

  20:       return container.Configure<TypeTrackingExtension>().CanResolve<T>();

  21:     }

  22:     /// <summary>

  23:     /// Determines whether this type can be resolved with the specified name.

  24:     /// </summary>

  25:     /// <typeparam name="T">The type to test for resolution</typeparam>

  26:     /// <param name="container">The unity container.</param>

  27:     /// <param name="name">The name associated with the type.</param>

  28:     /// <returns>

  29:     ///     <c>true</c> if this instance can resolve; otherwise, <c>false</c>.

  30:     /// </returns>

  31:     public static bool CanResolve<T>(this IUnityContainer container, string name)

  32:     {

  33:       return container.Configure<TypeTrackingExtension>().CanResolve<T>(name);

  34:     }

  35:     /// <summary>

  36:     /// Determines whether this instance can be resolved at all with or without a name.

  37:     /// </summary>

  38:     /// <typeparam name="T">The type to test for resolution</typeparam>

  39:     /// <param name="container">The unity container.</param>

  40:     /// <returns>

  41:     ///     <c>true</c> if this instance can resolve; otherwise, <c>false</c>.

  42:     /// </returns>

  43:     public static bool CanResolveAny<T>(this IUnityContainer container)

  44:     {

  45:       return container.Configure<TypeTrackingExtension>().CanResolveAny<T>();

  46:     }

  47:     #endregion

  48:  

  49:     #region TryResolve

  50:     /// <summary>

  51:     /// Tries to resolve the type, returning null if not found.

  52:     /// </summary>

  53:     /// <typeparam name="T">The type to try and resolve</typeparam>

  54:     /// <param name="container">The unity container.</param>

  55:     /// <returns>An object of type <see cref="T"/> if found, or <c>null</c> if not.</returns>

  56:     public static T TryResolve<T>(this IUnityContainer container)

  57:     {

  58:       return container.Configure<TypeTrackingExtension>().TryResolve<T>();

  59:     }

  60:     /// <summary>

  61:     /// Tries to resolve the type with the specified of name, returning null if not found.

  62:     /// </summary>

  63:     /// <typeparam name="T">The type to try and resolve</typeparam>

  64:     /// <param name="container">The unity container.</param>

  65:     /// <param name="name">The name associated with the type.</param>

  66:     /// <returns>An object of type <see cref="T"/> if found, or <c>null</c> if not.</returns>

  67:     public static T TryResolve<T>(this IUnityContainer container, string name)

  68:     {

  69:       return container.Configure<TypeTrackingExtension>().TryResolve<T>(name);

  70:     }

  71:     /// <summary>

  72:     /// Tries to resolve the type, returning the passed in defaultValue if not found.

  73:     /// </summary>

  74:     /// <typeparam name="T">The type to try and resolve</typeparam>

  75:     /// <param name="container">The unity container.</param>

  76:     /// <param name="defaultValue">The default value.</param>

  77:     /// <returns>An object of type <see cref="T"/> if found, or the <see cref="defaultValue"/> if not.</returns>

  78:     public static T TryResolve<T>(this IUnityContainer container, T defaultValue)

  79:     {

  80:       return container.Configure<TypeTrackingExtension>().TryResolve<T>(defaultValue);

  81:     }

  82:     /// <summary>

  83:     /// Tries to resolve the type, returning the passed in defaultValue if not found.

  84:     /// </summary>

  85:     /// <typeparam name="T">The type to try and resolve</typeparam>

  86:     /// <param name="container">The unity container.</param>

  87:     /// <param name="name">The name associated with the type.</param>

  88:     /// <param name="defaultValue">The default value.</param>

  89:     /// <returns>An object of type <see cref="T"/> if found, or the <see cref="defaultValue"/> if not.</returns>

  90:     public static T TryResolve<T>(this IUnityContainer container, string name, T defaultValue)

  91:     {

  92:       return container.Configure<TypeTrackingExtension>().TryResolve<T>(name, defaultValue);

  93:     }

  94:     #endregion

  95:  

  96:     #region ResolveAll

  97:     /// <summary>

  98:     /// Resolves all elements of a type, including the default.

  99:     /// </summary>

 100:     /// <typeparam name="T">The type to resolve</typeparam>

 101:     /// <param name="container">The unity container.</param>

 102:     /// <returns><see cref="IEnumerable"/> of T</returns>

 103:     public static IEnumerable<T> ResolveAllToEnumerable<T>(this IUnityContainer container)

 104:     {

 105:       return container.Configure<TypeTrackingExtension>().ResolveAll<T>();

 106:     }

 107:     /// <summary>

 108:     /// Resolves all registered T in the container, conditionally including the default unnamed

 109:     /// registered T. When includeDefault is false, this is the same as the normal Unity

 110:     /// ResolveAll.

 111:     /// </summary>

 112:     /// <typeparam name="T">The type to resolve</typeparam>

 113:     /// <param name="container">The unity container.</param>

 114:     /// <param name="includeDefault">if set to <c>true</c> include default value, else do not include default.</param>

 115:     /// <returns><see cref="IEnumerable"/> of T</returns>

 116:     public static IEnumerable<T> ResolveAllToEnumerable<T>(this IUnityContainer container, bool includeDefault)

 117:     {

 118:       return container.Configure<TypeTrackingExtension>().ResolveAll<T>(includeDefault);

 119:     }

 120:     /// <summary>

 121:     /// Resolves all elements of a type, including the default, and returns 

 122:     /// as an array of T.

 123:     /// </summary>

 124:     /// <typeparam name="T">The type to resolve</typeparam>

 125:     /// <param name="container">The unity container.</param>

 126:     /// <returns>Array of T</returns>

 127:     public static T[] ResolveAllToArray<T>(this IUnityContainer container)

 128:     {

 129:       return container.Configure<TypeTrackingExtension>().ResolveAllToArray<T>();

 130:     }

 131:     /// <summary>

 132:     /// Resolves all registered T in the container, conditionally including the default unnamed

 133:     /// registered T. When includeDefault is false, this is the same as the normal Unity

 134:     /// ResolveAll.

 135:     /// </summary>

 136:     /// <typeparam name="T">The type to resolve</typeparam>

 137:     /// <param name="container">The unity container.</param>

 138:     /// <param name="includeDefault">if set to <c>true</c> include default value, else do not include default.</param>

 139:     /// <returns>Array of T</returns>

 140:     public static T[] ResolveAllToArray<T>(this IUnityContainer container, bool includeDefault)

 141:     {

 142:       return container.Configure<TypeTrackingExtension>().ResolveAllToArray<T>(includeDefault);

 143:     }

 144:     #endregion

 145:   }

 146: }

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

   1: container.TryResolve<ITest>();

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.

TypeTrackingExtensionsReferencesPart Two – Type Tracking Usage Sample

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:

   1: using hazware.unity.extensions;

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

   1: IUnityContainer container = new UnityContainer();

   2: container.AddNewExtension<TypeTrackingExtension>();

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

   1: Console.WriteLine("CanResolve<IFoo>() == {0}", container.CanResolve<IFoo>());

   2: Console.WriteLine("CanResolve<IBar>() == {0}", container.CanResolve<IBar>());

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

   1: class Program

   2: {

   3:   static void Main(string[] args)

   4:   {

   5:     IUnityContainer container = new UnityContainer();

   6:     container.AddNewExtension<TypeTrackingExtension>();

   7:  

   8:     container.RegisterType<IFoo, AFoo>();

   9:     container.RegisterType<IFoo, AnotherFoo>("Named");

  10:  

  11:     Console.WriteLine("CanResolve<IFoo>() == {0}", container.CanResolve<IFoo>());

  12:     Console.WriteLine("CanResolve<IFoo>(\"Named\") == {0}", container.CanResolve<IFoo>("Named"));

  13:     Console.WriteLine("CanResolve<IBar>() == {0}", container.CanResolve<IBar>());

  14:  

  15:     Console.WriteLine("TryResolve<IFoo>() == null ==> {0}", container.TryResolve<IFoo>() == null);

  16:     Console.WriteLine("TryResolve<IFoo>(\"Named\") == null ==> {0}", container.TryResolve<IFoo>("Named") == null);

  17:     Console.WriteLine("TryResolve<IBar>() == null ==> {0}", container.TryResolve<IBar>() == null);

  18:     

  19:     Console.WriteLine("TryResolve<IBar>(new ABar()) == null ==> {0}", container.TryResolve<IBar>(new ABar()) == null);

  20:     Console.WriteLine("TryResolve<IBar>(\"Named\", new ABar()) == null ==> {0}", container.TryResolve<IBar>("Named", new ABar()) == null);

  21:  

  22:     Console.WriteLine("ResolveAllToEnumerable<IFoo>().Count() == {0}", container.ResolveAllToEnumerable<IFoo>().Count());

  23:     Console.WriteLine("ResolveAllToEnumerable<IFoo>(false).Count() == {0}", container.ResolveAllToEnumerable<IFoo>(false).Count());

  24:     Console.WriteLine("ResolveAllToEnumerable<IBar>().Count() == {0}", container.ResolveAllToEnumerable<IBar>().Count());

  25:  

  26:     Console.WriteLine("ResolveAllToArray<IFoo>().Length == {0}", container.ResolveAllToArray<IFoo>().Length);

  27:     Console.WriteLine("ResolveAllToArray<IFoo>(false).Length == {0}", container.ResolveAllToArray<IFoo>(false).Length);

  28:     Console.WriteLine("ResolveAllToArray<IBar>().Length == {0}", container.ResolveAllToArray<IBar>().Length);

  29:   }

  30: }

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.


Kick It on DotNetKicks.com
Share this
14 Comments - Leave a comment
  1. Allen says:

    Appears that if the RegisterEventArgs to event OnNewType do not have a value for e.TypeFrom, bad things happen. I solved this in my own way by simply changing all the RegisterType statements to look like:
    …RegisterType();
    instead of
    …RegisterType();

    to avoid this error.

    viz

    private void OnNewType(object sender, RegisterEventArgs e)
    {
    HashSet names;
    string name = string.IsNullOrEmpty(e.Name) ? string.Empty : e.Name;
    if (e.TypeFrom == null)
    throw new ArgumentNullException(“The TypeFrom argument cannot be null – use .RegisterType(); instead of
    …RegisterType(); to avoid this error”);
    if (!_registeredTypes.TryGetValue(e.TypeFrom, out names))
    { // not found, so add it
    _registeredTypes.Add(e.TypeFrom, new HashSet(new string[] { name }));
    }
    else
    { // already added type, so add name
    names.Add(name);
    }
    }

    • david says:

      Can you provide a test case that causes this problem? I would like to add it to the unit tests and then I can verify the solution you provided and add it in.

  2. Allen says:

    RegisterType(&lt T,T &gt) is what was supposed to show up. !!!

  3. Allen says:

    Dang! Anyway, pass from and to types to register type!!!

  4. Allen says:

    Sorry for the lack of clarity here. Let me see if I can put in the right example.

  5. Allen says:

    So I see that I failed to send you an example to test with. My bad. Somewhere in my calling code I was passing a null for the type to the RegisterType() of Unity, which will raise an ArgumentNullException. So I am trapping it in this extension handler in order to not blow up with no message. Since all my code is now much more mature it is difficult to determine where I made this mistake anymore, but if you create a test passing null to one of the Unity RegisterType calls it will raise the ArgumentNullException here and then all is not well….


    private void OnNewType(object sender, RegisterEventArgs e)
    {
    HashSet names;
    string name = string.IsNullOrEmpty(e.Name) ? string.Empty : e.Name;
    if (e.TypeFrom == null)
    throw new ArgumentNullException("The TypeFrom argument cannot be null – use .RegisterType(,); instead of …RegisterType(); to avoid this error");

    if (!_registeredTypes.TryGetValue(e.TypeFrom, out names))
    { // not found, so add it
    _registeredTypes.Add(e.TypeFrom, new HashSet(new string[] { name }));
    }
    else
    { // already added type, so add name
    names.Add(name);
    }

  6. Allen says:

    On another note, is there some way to get rid of these compiler warnings?

    BTW: For my own reasons, I have put your extensions into my Helpers namespace but otherwise this is the same UnityExtensions.cs and TypeTrackingExtensions.cs. If you are not comfortable with that I will go change the namespace references throughout.

    Helpers\TypeTrackingExtension.cs(52,66): warning CS1570: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension’ has badly formed XML — ‘A name contained an invalid character.’
    Helpers\TypeTrackingExtension.cs(65,33): warning CS1591: Missing XML comment for publicly visible type or member ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.Initialize()’
    Helpers\TypeTrackingExtension.cs(71,30): warning CS1591: Missing XML comment for publicly visible type or member ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.Remove()’
    Helpers\TypeTrackingExtension.cs(103,30): warning CS0168: The variable ‘ex’ is declared but never used
    Helpers\TypeTrackingExtension.cs(131,30): warning CS0168: The variable ‘ex’ is declared but never used
    Helpers\TypeTrackingExtension.cs(208,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.TryResolve()’ has cref attribute ‘T’ that could not be resolved
    Helpers\TypeTrackingExtension.cs(219,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.TryResolve(string)’ has cref attribute ‘T’ that could not be resolved
    Helpers\TypeTrackingExtension.cs(230,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.TryResolve(T)’ has cref attribute ‘T’ that could not be resolved
    Helpers\TypeTrackingExtension.cs(230,89): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.TryResolve(T)’ has cref attribute ‘defaultValue’ that could not be resolved
    Helpers\TypeTrackingExtension.cs(244,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.TryResolve(string, T)’ has cref attribute ‘T’ that could not be resolved
    Helpers\TypeTrackingExtension.cs(244,89): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.TryResolve(string, T)’ has cref attribute ‘defaultValue’ that could not be resolved
    Helpers\TypeTrackingExtension.cs(260,35): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.ResolveAll()’ has cref attribute ‘IEnumerable’ that could not be resolved
    Helpers\TypeTrackingExtension.cs(273,35): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.TypeTrackingExtension.ResolveAll(bool)’ has cref attribute ‘IEnumerable’ that could not be resolved
    Helpers\UnityExtensions.cs(102,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.TryResolve(Microsoft.Practices.Unity.IUnityContainer)’ has cref attribute ‘T’ that could not be resolved
    Helpers\UnityExtensions.cs(114,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.TryResolve(Microsoft.Practices.Unity.IUnityContainer, string)’ has cref attribute ‘T’ that could not be resolved
    Helpers\UnityExtensions.cs(126,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.TryResolve(Microsoft.Practices.Unity.IUnityContainer, T)’ has cref attribute ‘T’ that could not be resolved
    Helpers\UnityExtensions.cs(126,89): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.TryResolve(Microsoft.Practices.Unity.IUnityContainer, T)’ has cref attribute ‘defaultValue’ that could not be resolved
    Helpers\UnityExtensions.cs(139,53): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.TryResolve(Microsoft.Practices.Unity.IUnityContainer, string, T)’ has cref attribute ‘T’ that could not be resolved
    Helpers\UnityExtensions.cs(139,89): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.TryResolve(Microsoft.Practices.Unity.IUnityContainer, string, T)’ has cref attribute ‘defaultValue’ that could not be resolved
    Helpers\UnityExtensions.cs(154,35): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.ResolveAllToEnumerable(Microsoft.Practices.Unity.IUnityContainer)’ has cref attribute ‘IEnumerable’ that could not be resolved
    Helpers\UnityExtensions.cs(168,35): warning CS1574: XML comment on ‘AASHTO.ElementMigration.VisualElementMigrator.Helpers.UnityExtensions.ResolveAllToEnumerable(Microsoft.Practices.Unity.IUnityContainer, bool)’ has cref attribute ‘IEnumerable’ that could not be resolved

  7. Shirl says:

    In the complicated world we live in, it’s good to find simple soluiotns.

Leave a comment

Your email address will not be published. Required fields are marked *

*


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


Welcome , today is Saturday, May 19, 2012
Statistical data collected by Statpress SEOlution (blogcraft).