Archive for May 15th, 2008

A Basic Hands on Introduction to Unity DI Container

May 15th, 2008 by Sidar Ok

Hey folks, here we are with another interesting article. There are some introductions already on the internet about Unity providing the theoretical information, so I won’t go deeper in that route. In this article, I will be more practical and provide a concrete implementation of concepts. You can download the sample codes clicking here.

Microsoft Patterns and Practices team had been developing Enterprise Library to enable the use of general patterns and practices for .NET platform, which has great pluggable application blocks such as Logging and Validation application blocks. One of them used to be DIAB, which is an acronym for Dependency Injection Application Block. But folks thought it should be named differently from the other application blocks, and came with the fancy name “Unity”.

Now I won’t go to details of Inversion of Control and Dependency Injection patterns as I can imagine you are sick of them and I want to keep this post short, but the basic value it brings to enterprise systems is decoupling. They promote programming to interfaces and isolate you from the creation process of the collaborators, letting you to concentrate on what you need to deliver while improving testing.

Out in the universe, there are big frameworks such as Spring.NET or Castle Windsor containing Castle Microkernel. The choice coming from Microsoft Patterns and Practices team is the Unity framework, which has gone live in the April. It is open source and hosted in CodePlex along with its community contributions project that is awaiting developers’ helps to extend unity.

Enough talking, lets see some action. We will develop a simple set of classes that does naming, applying strategy patterns. This is also good because a common best practice is to inject your strategies to your consumers through containers and interfaces.

Setting Up the Environment to Use Unity

In the example, I used Visual Studio 2008 and .NET 3.5. You need to download the latest drop of Unity from here and add it as a reference to the projects we want to use and that’s it really.

Members of the Solution

In the UnitySample project, there are Strategy Contracts and Strategy Implementations. The contracts are interfaces as you already may have discovered, where their implementations reside in the implementations project.

So in the Contracts we have a naming strategy contract as follows:

   2: /// Defines the contract of changing strings per conventions.
   3: /// </summary>
   4: public interface INamingStrategy
   5: {
   6:   /// <summary>
   7:   /// Converts the string according to the convention.
   8:   /// </summary>
   9:   /// <param name=”toApplyNaming”>The string that naming strategy will be applied onto. 
  10:   /// Assumes that the words are seperated by spaces.</param>
  11:   /// <returns>The naming applied string.</returns>
  12:   string ConvertString(string toApplyNaming);
  13: }

And we will have 2 concrete implementations, one for Pascal and one for Camel casing in the implementations project. Being good TDD Guys we are writing the test first. Let’s see the test method for Pascal casing (camel’s is pretty much similar to it):

   1: /// <summary>
   2: ///A test for ConvertString
   3: ///</summary>
   4: [TestMethod()]
   5: public void ConvertStringTest()
   6: {
   7:   INamingStrategy strategy = new PascalNamingStrategy();
   9:   string testVar = “the variable to be tested”;
  10:   string expectedVar = “TheVariableToBeTested”;
  12:   string resultVar = strategy.ConvertString(testVar);
  14:   Assert.AreEqual(expectedVar, resultVar);
  15: }

After we write the tests and fail, we are ready to write the concrete implementation for the Pascal Casing to pass the test:

   1: /// <summary>
   2: /// Pascal naming convention, all title case.
   3: /// </summary>
   4: public class PascalNamingStrategy : INamingStrategy
   5: {
   6:    #region INamingStrategy Members
   8:     /// <summary>
   9:     /// Converts the string according to the convention.
  10:     /// </summary>
  11:     /// <param name=”toApplyNaming”>The string that naming strategy will be applied onto. Assumes that the words are seperated by spaces.</param>
  12:     /// <returns>The naming applied string.</returns>
  13:     public string ConvertString(string toApplyNaming)
  14:     {
  15:         Debug.Assert(toApplyNaming != null);
  16:         Debug.Assert(toApplyNaming.Length > 0);
  18:         // trivial example, not considering edge cases.
  19:         string retVal = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(toApplyNaming);
  20:         return retVal.Replace(” “, string.Empty);
  21:     }
  23:     #endregion
  24: }

You can see the relevant implementation of the Camel Casing in the source codes provided.

After finishing with fundamental, let’s utilize & test Unity with our design. For this purpose I am creating a project called “Unity Strategies Test” to see how container can be used to inject in when a INamingStrategy is requested. Following test method shows very simple injection and test if the injection succeeded in a few lines:

   1: /// <summary>
   2: /// Test if injecting dependencies succeed.
   3: /// </summary>
   4: [TestMethod]
   5: public void ShouldInjectDependencies()
   6: {
   7:     IUnityContainer container = new UnityContainer();
   9:     container.RegisterType<INamingStrategy, PascalNamingStrategy>(); //we will abstract this later 
  11:     INamingStrategy strategy = container.Resolve<INamingStrategy>();
  13:     Assert.IsNotNull(strategy, “strategy injection failed !!”);
  14:     Assert.IsInstanceOfType(strategy, typeof(PascalNamingStrategy), “Strategy injected, but type wrong!”);
  16: }

And the testing of PascalNamingStrategy becomes much easier and more loosely coupled now:

   1: /// <summary>
   2: /// Tests the pascal strategy through injection.
   3: /// </summary>
   4: [TestMethod]
   5: public void TestPascalStrategy()
   6: {
   7:    IUnityContainer container = new UnityContainer();
   9:    container.RegisterType<INamingStrategy, PascalNamingStrategy>(); //we will abstract this later 
  11:    // notice that we dont know what strategy will be used, and we dont care either really
  13:    INamingStrategy strategy = container.Resolve<INamingStrategy>();
  15:    string testVar = “the variable to be tested”;
  16:    string expectedVar = “TheVariableToBeTested”;
  17:    string resultVar = strategy.ConvertString(testVar);
  19:    Assert.AreEqual(expectedVar, resultVar);
  20: }

This very basic example showed how your tests and code can become loosely coupled. In the next posts I will try to talk about configuring the container, and how to utilize it in your web applications. Stay tuned till then.

kick it on

Share it on: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • Sphinn
  • Facebook
  • Mixx
  • Google
  • Blogosphere News
  • e-mail
  • YahooMyWeb
  • DotNetKicks
  • DZone