Month: August 2012

Adding a static reference into a unity configuration file


Hi,

I’d like to talk about how you can set up your unity configuration file to resolve static references. This is handy depending of the context, for example you would like to register the Path Separator of the file system. This if you’re on unix-based system it’s more likely to be “/” and if you are on a Windows-based system it’s going to be “\”. Certainly you could use configuration files, for this purpose, this is just an alternative where you could let you application know about specific values without knowing they’re coming from, and you usually do this for test-ability.

For those who does not have enough patience, the source code is at https://github.com/hmadrigal/playground-dotnet/tree/master/MsUnity.TypeConverters

The problem

I’d like to set my Unity Container to take the value from a static field, so I do not have to write code to set up a the container in code and in the configuration file.

 

The Solution

Unity Container is very flexible and moreover extensible. It takes advantage of a pattern called “TypeConverter”, which basically it’s an specialized class which maps from one type to another. Particularly in our case we will be mapping from System.string value to any valid static value by using reflection.

Type converters are used along .NET framework, here is a quick guide of How to: Implement a Type Converter:
http://msdn.microsoft.com/en-us/library/ayybcxe5.aspx

In our case, we will assume that we’re receiving a value of type string which follows the following format:

{member}@{assemblyQualifiedName}

Then, we can reference static fields by using the following syntax:

Version@System.Environment, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

The type converter class that does this work is the following:

 

using System;
using System.ComponentModel;
using System.Reflection;

namespace EntLibUnity.Extensions
{
    /// <summary>
    /// Converts an (formatted) string to a reference of a given static member.
    /// The string uses this format: {member}@{assemblyQualifiedName}
    /// For example:
    ///     Version@System.Environment, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    /// </summary>
    public class StringToStaticInstanceTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return (typeof(string) == sourceType) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            string stringValue;
            if (value == null
                || (stringValue = value as string) == null
                || string.IsNullOrEmpty(stringValue)
                || !stringValue.Contains("@")
            )
            {
                return null;
            }

            var stringParts = stringValue.Split('@');
            if (stringParts.Length != 2)
            {
                return null;
            }
            var propertyPath = stringParts[0];
            var propertyPathParts = propertyPath.Split('.');
            var assemblyQualifiedName = stringParts[1];
            // Gets the static member
            var currentClassType = Type.GetType(assemblyQualifiedName, true);
            var currentPropertyInfo = currentClassType.GetProperty(propertyPathParts[0],
                                                                 BindingFlags.Public | BindingFlags.Static |
                                                                 BindingFlags.FlattenHierarchy);
            var currentPropertyValue = currentPropertyInfo.GetValue(null, null);
            // Loops into the path to get a value
            for (var i = 1; i < propertyPathParts.Length; i++)
            {
                currentPropertyInfo = currentClassType.GetProperty(propertyPathParts[i]);
                currentPropertyValue = currentPropertyInfo.GetValue(currentPropertyValue, null);
            }
            return currentPropertyValue ?? base.ConvertFrom(context, culture, value);
        }
    }
}

The second step is to configure our container to recognize the TypeConverter and use it when needed. This is simple, when we’re registering types in the configuration file we have the option of specifying a type converter as you can see in the following sample:

<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <!-- Using Design-Time Configuration: http://msdn.microsoft.com/en-us/library/ff660935(v=PandP.20).aspx#format_config -->
  <!-- The Unity Configuration Schema: http://msdn.microsoft.com/en-us/library/ff660914(v=PandP.20).aspx -->
  <!-- Specifying Types in the Configuration File http://msdn.microsoft.com/en-us/library/ff660933(v=PandP.20).aspx#_Default_Aliases_and-->

  <!-- Setting an alias for our TypeConverter, to prevent using the full type reference -->
  <alias alias="StringToStaticInstanceTypeConverter" type="EntLibUnity.Extensions.StringToStaticInstanceTypeConverter, EntLibUnity.Extensions" />

  <alias alias="IVersionManager" type="EntLibUnity.Infrastructure.IVersionManager, EntLibUnity.UnitySample.ConsoleApp" />
  <alias alias="VersionManager" type="EntLibUnity.UnitySample.VersionManager, EntLibUnity.UnitySample.ConsoleApp" />

  <!-- Default (unnamed) container-->
  <container>
    <register type="IVersionManager" mapTo="VersionManager">
      <constructor>
        <param name="version">
          <!-- In this case we use the expanded version of Param and set the proper typeConverter attribute-->
          <value value="Version@System.Environment, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" typeConverter="StringToStaticInstanceTypeConverter" />
        </param>
      </constructor>
    </register>
  </container>

</unity>

Simple ;-). Finally we only have to use our container as we usually use it. In my case I’ve some extensions to load and configure the container, you can check them by downloading the source code.
Here is the final code of our main application:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using EntLibUnity.Extensions;
using EntLibUnity.Infrastructure;

namespace EntLibUnity.UnitySample.ConsoleApp
{
    class Program
    {
        private static IUnityContainer container;

        static void Main(string[] args)
        {
            container =
                new UnityContainer()
                .LoadContainerFromSection()
                .LoadEnterpriseLibraryTypes();

            var versionManager = container.Resolve<IVersionManager>();
            Console.WriteLine(versionManager.Version);
            Console.ReadKey();
        }
    }
}

The source code is at https://github.com/hmadrigal/playground-dotnet/tree/master/MsUnity.TypeConverters

Your comments are welcome,
kind regards,
Herber

Advertisements

Life tiles into your Modern (Metro) Application (WinRT)


Hello,

 

Today I have an idea for an application using all “modern” (formerly Metro). As part of this idea I needed a Life tile. I look quickly into the SDK but not found a reference of how any hub tile control built-in in WinRT SDK. Thus my second idea was to import one already done in Windows Phone Toolkit. This last approach worked smoothly. In my example I’m using code decompiled by dotTrace, but since Windows Phone Toolkit is open source you can go to codeplex side and download it.

As usual you can get the source code from my github account at: https://github.com/hmadrigal/playground-dotnet/tree/master/MsWinRT.HubTileSample

The problem

I want to include hub tiles (life tiles) into my Modern (Metro/WinRT) application.

The solution

Import the HubTile control from the Windows Phone toolkit at http://silverlight.codeplex.com/releases/view/60291 and import this control to WinRT.

In reality I decompiled the code instead of importing it, but it would have been easier to download it. In any case my example is using decompile code, and it’s based on the Grid Template. There is not much work behind it, only decompile, copy, paste and compile. There were few changes, but they’re not worth to mention. That said, here is the control, and I hope you can have some fun with it.

https://github.com/hmadrigal/playground-dotnet/tree/master/MsWinRT.HubTileSample