Working With Configuration Files In Unity

July 24, 2008

Working With Configuration Files In Unity

In the previous posts about Unity I Unity Application Block
discussed basic concepts and
showed how to use Unity
in ASP.NET web forms. 
In this post I’m going to
show how to use Unity with configuration files.

The Unity Configuration Section
In order to start working with configuration files with Unity the first thing
to understand is the configuration section. Lets start with an example of
a Unity configuration section and then discuss the things that can be configure:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <configSections>

    <section name="unity"

      type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,

      Microsoft.Practices.Unity.Configuration, Version=1.1.0.0,

      Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

  </configSections>

  <unity>

    <typeAliases>

      <!– Lifetime manager types should be inserted

          if you need lifetime managers –>

      <typeAlias alias="singleton"

          type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,

            Microsoft.Practices.Unity" />

      <typeAlias alias="external"

          type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager,

            Microsoft.Practices.Unity" />

 

      <!– User defined type aliases –>

      <!– An interface for logger implementation –>

      <typeAlias alias="ILogger"

          type="UnityExamples.Common.ILogger,

          UnityExamples.Common" />

      <!– An abstarct class for database classes –>

      <typeAlias alias="Database"

          type="UnityExamples.Common.Database,

          UnityExamples.Common" />

    </typeAliases>

    <containers>

      <container>

        <types>

          <type type="ILogger"

                mapTo="UnityExamples.Common.FileLogger,

                UnityExamples.Common">

            <!– Will be configured as singleton by the lifetime

                manager above –>

            <lifetime type="singleton" />

          </type>

          <type type="Database"

                mapTo="UnityExamples.Common.CustomDatabase,

                UnityExamples.Common">

            <typeConfig

              extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,

                Microsoft.Practices.Unity.Configuration">

              <constructor>

                <param name="connString" parameterType="System.String">

                  <value value="connection value…"/>

                </param>

                <param name="logger" parameterType="ILogger">

                  <dependency />

                </param>

              </constructor>

            </typeConfig>

          </type>

        </types>

      </container>

    </containers>

  </unity>

</configuration>

TypeAliases Element
The first thing to notice is the typeAliases element that holds all the aliases
that you want to give to the type you are going to use with the Unity container.
It can reduce the code in the configuration section of the container itself instead
of using the long type definition. In the example above there are four typeAliases:
singleton, external, ILogger and Database. You can see the use of the aliases in
the container section itself.

Containers Element
The containers section is holding all the containers information that you need to
configure. You can have more than one type of container. The way to distinguish
between the containers is the name attribute that can be assigned to every container.
In the container you can define the types that will be injected in the the dependency
injection
process. Every type is mapped to another type by the mapTo attribute.
The mapTo attribute will inform the container that the registered type will map to the
type that was written in the attribute. Another thing that I show in the example is the
lifetime element of the type element. The lifetime element will instruct the
Unity container how the registered element will be constructed. In the example above
the FileLogger class will be constructed as a singleton.

TypeConfig Element
In the type element we can register a typeConfig element that can help us
to configure the injection to the constructor, method or properties of that type.
In my example I inject a connection string and a logger object to the
CustomDatabase object. The dependency element in the constructor parameter of
the logger instruct the Unity container that the element itself need to be injected with
the registered type of ILogger.

A Note
There are three more elements that can be configured inside the container element
which are instances, extensions and extensionConfig. I’m not going to discuss them
but you can read about them in the Unity documentation.

The Classes I Used in The Example
The abstract Database class:

    public abstract class Database

    {

    }

The CustomDatabase class:

    public class CustomDatabase : Database

    {

        #region Members

 

        private ILogger _logger;

        private string _strConnString;

 

        #endregion

 

        #region Ctor

 

        /// <summary>

        /// Construct a new CustomDatabase object

        /// </summary>

        public CustomDatabase(string connString, ILogger logger)

        {

            _logger = logger;

            _strConnString = connString;

        }

 

        #endregion

    }

The ILogger interface:

    public interface ILogger

    {

        #region Methods

 

        void Log(string message);

 

        #endregion

    }

The FileLogger class:

    public class FileLogger : ILogger

    {

        #region ILogger Members

 

        public void Log(string message)

        {

        }

 

        #endregion

    }

How To Plug The Configuration File To Unity
After a lot of configuration discussion you probably want to see some
real code of how to use the configuration section. The following code
will show you how to do it.

   IUnityContainer container = new UnityContainer();

 

   var section =

      (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

 

   section.Containers.Default.Configure(container);

 

   var database = container.Resolve<Database>();

   var logger = container.Resolve<ILogger>();

First build a new Unity container. Then get the configuration section of
Unity. The last thing to do is to use the Configure method of the relevant
container (in my example the default container) on the container object itself.
After the three steps you can use the container to inject the dependencies
to the types that were written in the configuration file by using the Resolve
method.

Summary
In today post I showed how to use configuration files in order to configure a
Unity container. I showed the main elements in the configuration file and also
showed a code of how to use it in an application. One last thing, the Unity
application block
was released as stand alone dll and also with enterprise library.
I would expected from the patterns & practices team to provide a designer to Unity
like in all the other application blocks. Maybe it will be in the next enterprise library
release…

Add comment
facebook linkedin twitter email

Leave a Reply

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>

5 comments

  1. shmulikJuly 25, 2008 ב 4:23

    hi,
    how do you configure type with generics.
    for instance:
    container.RegisterType(typeof(IValidator<>), typeof(Validator<>),
    new ContainerControlledLifetimeManager());

    Reply
  2. shmulikJuly 25, 2008 ב 4:29

    hi,
    how do you configure types with generics ?
    for instance:
    container.RegisterType(typeof(IValidator<>), typeof(VBAValidator<>),
    new ContainerControlledLifetimeManager());

    Reply
  3. Gil FinkJuly 25, 2008 ב 9:07

    Hi shmulik,
    A good question. I wanted to write apost in the subject (and I will). The answer is simple. Lets take your generic IValidator<>. When you write the type of IValidator in the config file you’ll write IValidator`1 where ` indicate that it’s generic type and 1 indicate that it recieves one generic type:

    In the code after building the container you use Resolve method with the type you need and it’s generic parameter:
    var validator = container.Resolve>();
    Hope it helps,
    Gil

    Reply
  4. TimDecember 19, 2008 ב 23:58

    In the sample config file, the ILogger instance is being injected into the constructor via the
    –> –> tree for the CustomDatabase type. Is this really needed? I thought unity would automagically inject the registered ILogger type during the build up of the CustomDatabase.

    Thanks for the example though. I can see how the config node would benefit injecting data or a type that is not already registered with the container.

    Reply
  5. Gil FinkDecember 20, 2008 ב 9:11

    @Tim,
    In the example it isn’t needed to indicate the ILogger instance but I did it for some reasons. The first is for showing the elements that can be used in the config files. The second is to explicitly indicate the dependency which as you wrote isn’t always needed.
    I’m glad the example could help you.

    Reply