Archive for the ‘Dependency Injection’ Category

What is this Managed Extensibility Framework thing all about ?

September 26th, 2008 by Sidar Ok

No, this is not another introduction post. Being one of the earliest adopter of MEF, I started to see a great confusion around what MEF is, and what it really is suppose to do in this wild world of DI containers… Well ok, I can’t lie anymore about, as people have twitter proofs to throw at me, I was a part of that confusion :

image

As you see, I was pretty biased as an avid DI user, that MEF is an IoC container so why doesn’t it behave in a normal DI ish way ? I was seeing MEF as an only IoC container so much, and in that limited perspective its design has sucked big time for me, especially because of the unnatural Export - Import system. And for that matter, I even implemented a way of an external configuration for MEF.

This has proven to be really painful. Glenn Block, saw my pain through twitter and called me for an hour of a very nice and informative chat.

Here is the result: MEF is not a DI container. DI is only a part of the solution that MEF tries to bring into the scene. Ayende just got quicker in the game, and explained it well, so I couldn’t have the joy of telling the world first :)

I won’t repeat what Ayende said, I’ll just try to make things a bit more concrete in perspective of my understanding as a person who likes to talk over examples.

Understanding MEF with an example

Now, it is time to take those DI glasses off and look at a different view. Forget about DI, containers, IoCs et all. Let’s start thinking with a concrete example we all know about. Visual Studio has a plug in infrastructure. Say that we are handed to build that, what do we do ?

  1. First, we need to come up with an interface (be it an SDK or API reference), sort of a hook to outside, so addin implementors can code against it.

    1. This involves the lifecycle of the addin. You should be able to achieve basic needs create instance / retrieve already created one (singleton).

  2. We should be able to provide a way of interact with add-in. Add-in should be able to easily send you messages about, say show solution explorer or open a file in editor.

  3. We should be able to lazy load it if needed. E.g there is no need to load an add-in at start up when the add in is supposed to be performing within a context menu event.

  4. A new add-in, or a replace of an old one should be as easy as throwing the dll in bin folder. This means that if a new set of addins is in place, you need to be able to choose amongst them. (meta-data based discovery)

  5. When an add-in is replaced or simply dead, we need to unload it.

So in all this sense, VS is a composite application. It needs to be composed dynamically.Beware, during all these steps we still don’t care about the actual add-in. We just care that if it complies to our needs that we specified in the contract. We need something that quacks, and looks like a duck. Anything that supplies these demands, even if it is a dog, more than welcome to be part of our Visual Studio.

Now, these are all huge works. Imagine just lazy loading of a component has a lot of edge cases already(#3), let alone solving the unloading problem from AppDomain(#5). But let’s say that we finished and shipped our Visual Studio. Happy days, counting the money.

And now, we are assigned on a new task and writing Lutz Roeder’s great tool Reflector. And guess what, Lutz Roeder wants us to implement an add-in infrastructure so that they can perform several tasks in reflected code. To accomplish this, we need to do ALL the steps above again, from 1 to 5. All that drudge work, and none of it is reusable because we designed it in an application specific way (and that perfectly makes sense since our concern was not to build that framework). Now you got the point: MEF is a core .NetFx component that adds ability of composability to any app by default.  Its aim in short term is, not replacing IoC containers but working with IoC containers, which fits this greater vision.

Another Example - Publisher Subscriber

A lot of confusion is also going around between MEF and System.Addin Namespace, similar to the confusion addressed above. Let’s look at another example that has nothing to do with add-ins, to show that problem is not an add-in bound system.

Say we have a banking system, with a strong domain model. We need services like Accounting, Personal Info, Leasing etc. And in this bank, in every two weeks or so there comes a new service.For the discovery and configuration of these new services, you would normally use an ESB (Enterprise Service Bus). That discovery part has indeed very similar roots with MEF.  MEF provides you a lightweight bus-alike approach for your extensions. By hosting MEF, you are delegating this discovery system to MEF, and it provides you a rich Meta Data to be used. The Export - Import model indeed looks very similar to Publisher and Subscriber model in this sense.

Conclusion

MEF is by no means a replacement to today’s IoC containers, nor to System.Addin . It aims to be a reusable solution to provide a common base for the heavy lifting code of extensible applications, so we (hopefully) will need to worry less about extensibility concerns of the application. If you like, you can use MEF as your IoC container, but this doesn’t mean that you should. We can also use our favorite IoC container of choice with a free (as in speech) collaboration with MEF by Resolvers.I am planning to cover the concepts with a hands on application which will hopefully help to build better understanding, stay tuned.

kick it on DotNetKicks.com

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

Building a Configuration Binder for MEF with POCO Support

July 14th, 2008 by Sidar Ok

After taking extensibility points of Managed Extensibility Framework to a spin,(which will be called “primitives” from next version on), Jason Olson has posted a nice way of enabling Fluent Interfaces and making MEF more compatible in a more DI ish way, and trying to enable support for POCOs.

When Krzystof Kcwalina announced first CTP of MEF, he made a comment that not attribute based programming model is feasible, and Jason has provided it in the post. But  appearantly the team is going to keep Import and Export model in the first CTP, according to David Kean’s reply to one of the replies in his blog post.

Now, that makes me cringe. Clearly, I don’t like this kind of magic. Somebody exports, somebody imports, and a-ha! I have a list of import info in my domain (which is another form of intrusiveness in your design).

In this post, I will build a Configuration Resolver that will use the application’s context configuration to resolve the values in the container with pure POCO support.  This is based on first CTP, and has a lot of hack, but I think involves some good work worth to look at.

All I want is to feed the container via an XML configuration (XmlRepository in our case) and get my dependencies injected in the configured way. If I had to mimic MEF approach, I would have come up a configuration like this:

   1: <?xml version=”1.0″ encoding=”utf-8″ ?>
   2: <configuration>
   3:   <configSections>
   4:     <section name=”xmlBinder” type=”XmlBinder.Configuration.XmlBinderConfigurationSection, XmlBinder” />
   5:   </configSections>
   6:   <xmlBinder>
   7:     <objects>
   8:       <object name=”HelloWorld” type=”XmlBinder.TestClasses.HelloWorld, XmlBinder.TestClasses”>
   9:         <import name=”Outputter” type=”XmlBinder.TestClasses.Interfaces.IOutputter, XmlBinder.TestClasses” contract=”outputContract”/>
  10:         <import name=”Greeter” type=”XmlBinder.TestClasses.Interfaces.IGreeter, XmlBinder.TestClasses” contract=”greetingContract”/>
  11:       </object>
  12:
  13:       <object name=”Outputter”>
  14:         <export name=”Outputter” type=”XmlBinder.TestClasses.Interfaces.Outputter, XmlBinder.TestClasses” contract=”outputContract” />
  15:       </object>
  16:
  17:       <object name=”Greeter”>
  18:         <export name=”" type=”XmlBinder.TestClasses.Interfaces.Greeter, XmlBinder.TestClasses” contract=”greetingContract” />
  19:       </object>
  20:     </objects>
  21:   </xmlBinder>
  22: </configuration>

But this didn’t seem natural to me. First, they need to share the contract name, which is prone to configuration errors.Second and export/import model is still in place - and in a worse format. I have gone for a model like this instead (looked a bit spring - unity mixture at the end)

   1: <?xml version=”1.0″ encoding=”utf-8″ ?>
   2: <configuration>
   3:   <configSections>
   4:     <section name=”xmlBinder” type=”XmlBinder.Configuration.XmlBinderConfigurationSection, XmlBinder” />
   5:   </configSections>
   6:   <xmlBinder>
   7:       <objects>
   8:         <object name=”HelloWorld” type=”XmlBinder.TestClasses.HelloWorld, XmlBinder.TestClasses”>
   9:           <properties>
  10:             <!–<property name=”PropertyName” destination=”XmlBinder.TestClasses.ConsoleOutputter, XmlBinder.TestClasses” /> Will be supported in the future, hopefully :)–>
  11:             <property name=”Outputter” type=”XmlBinder.TestClasses.Interfaces.IOutputter, XmlBinder.TestClasses” mapTo=”XmlBinder.TestClasses.ConsoleOutputter, XmlBinder.TestClasses” />
  12:             <property name=”Greeter” type=”XmlBinder.TestClasses.Interfaces.IGreeter, XmlBinder.TestClasses” mapTo=”XmlBinder.TestClasses.Greeter, XmlBinder.TestClasses” />
  13:           </properties>
  14:         </object>
  15:       </objects>
  16:   </xmlBinder>
  17: </configuration>

Here I have my XmlBinder.Configuration namespace to store my configuration related classes.

image

Figure 1. Configuration Classes

As you see, I am defining a configuration section which has a list of object configurations in it. Object has properties, and properties have names, source types and destination types to be mapped.  Now although there is an ok amount of code there, I am not gonna talk about how I parse the configuration information, if you are interested you can download the source and read the tests.

With all these in place, I want my POCO’s, who look like this like in Jason’s example, without any Imports or Exports:

   1: /// <summary>
   2: /// Plain old Hello World
   3: /// </summary>
   4: public class HelloWorld
   5: {
   6:     public IOutputter Outputter
   7:     {
   8:         get;
   9:         set;
  10:     }
  11: 
  12:     public IGreeter Greeter
  13:     {
  14:         get;
  15:         set;
  16:     }
  17: 
  18:     public void SayIt()
  19:     {
  20:         Outputter.Output(Greeter.Greet());
  21:     }
  22: }
  23: 
  24: public class ConsoleOutputter : IOutputter
  25: {
  26:     #region IConsoleOutputter Members
  27: 
  28:     public void Output(string message)
  29:     {
  30:         Console.WriteLine(message);
  31:     }
  32: 
  33:     #endregion
  34: }
  35: 
  36: public class Greeter : IGreeter
  37: {
  38:     #region IGreeter Members
  39: 
  40:     public string Greet()
  41:     {
  42:         return “Hellp World”;
  43:     }
  44: 
  45:     #endregion
  46: }
  47: 
  48: 

to be injected by the magic of only this code in the bind time:

   1: CompositionContainer container = new CompositionContainer(resolver);
   2: container.Bind();
   3: var helloWorld = container.TryGetBoundValue<HelloWorld>().Value;

To achieve this, we have to give the container the types and contracts in the format that it needs, and this is should be a cooked & ready to eat thing because since we are not giving the container Imports and exports, we have to tell it what to import and export. To find out what container wanted to do the binding was not as easy as I expected to be, I had to do a lot of reverse engineering. Here, TDD saved my day and helped me to divide my problem space into a distinct two - Provide the instances to Composition Container correctly(1) and Compose the requested objects by using the types that are provided by (1).

We need to write a resolver and a binder to achieve this. ValueResolver needs a repository to use in the resolving process, though it takes the repository as a parameter. This parameter is an ITypeRepository interface in my design which means that one can write their DbConfigRepository that implements this and pass it to the ConfigValueResolver, and expect the resolver to work in the same way. This approach decouples the value resolver from the internals of repository. ITypeRepository interface is defined as follows :

   1: public interface ITypeRepository
   2: {
   3:   /// <summary>
   4:   /// Gets the object meta.
   5:   /// </summary>
   6:   /// <returns>A list of object meta data info. This can be changed to return IEnumerable to enable lazy loading in the future.</returns>
   7:   IList<ObjectMeta> GetObjectMeta();
   8: }

And the implementation for this, that takes the Object Meta Data from configuration repository, in this case the application XML configuration, is as below:

   1: public class XmlTypeRepository : ITypeRepository
   2: {
   3:    #region ITypeRepository Members
   4:     public IList<ObjectMeta> GetObjectMeta()
   5:     {
   6:         XmlBinderConfigurationSection section = ConfigurationManager.GetSection(“xmlBinder”) as XmlBinderConfigurationSection;
   7:         Debug.Assert(section != null);
   8: 
   9:         IList<ObjectMeta> retVal = BuildObjectMetaListFromConfigurationSection(section);
  10: 
  11:         return retVal;
  12:     }
  13:    #endregion
  14: 
  15:     private IList<ObjectMeta> BuildObjectMetaListFromConfigurationSection(XmlBinderConfigurationSection section)
  16:     {
  17:             List<ObjectMeta> retVal = new List<ObjectMeta>();
  18: 
  19:         foreach (XmlBinderObjectElement objectElement in section.Objects)
  20:         {
  21:             ObjectMeta meta = BuildObjectMetaFromConfiguration(objectElement);
  22:             retVal.Add(meta);
  23:         }
  24:         return retVal;
  25:     }
  26: 
  27:     private ObjectMeta BuildObjectMetaFromConfiguration(XmlBinderObjectElement element)
  28:     {
  29:         Debug.Assert(element != null);
  30: 
  31:         ObjectMeta retVal = new ObjectMeta()
  32:         {
  33:              ObjectType = element.Type,
  34:         };
  35:
  36:         foreach (XmlBinderPropertyElement propertyElement in element.PropertyElements)
  37:         {
  38:             retVal.MappingPairs.Add(new TypeMappingPair(element.Type.GetProperty(propertyElement.Name), propertyElement.TypeToMap, propertyElement.Name));
  39:
  40:         }
  41: 
  42:         return retVal;
  43:     }
  44: }

Here, ObjectMeta represents an object’s meta data to be processed further to be meaningful to bind.

image

Figure 2: TypeMappingPair and ObjectMeta entity structures

Now that we have the repository, we can safely build the resolver. The relationship between resolver and a binder is this as far as I could find out: A binder is there for a type, is responsible of it to be build properly. Binder tells to the container for the type “this type exports these, and imports these. Now go build.”. So it is reasonable for a binder to take 3 piece of information: Target type, its imports and its exports. I wrapped them up in a BindingInfo entity whose class diagram is shown below with side by side to ObjectMeta:

image

Figure 3: BindingInfo and ObjectMeta objects

Have you noticed the mismatch between two ? That’s the key point, BindingInfo is what binder (and so container) needs, and ObjectMeta is what we have, and is more intuitive and is there to support POCO model. Now we need to implement the magic on our own to convert from ObjectMeta listo to Binding Info list. I implemented this method called GetBindingInfo() into the resolver. Resolver queries the underlying repository the first time it is asked to do so, and retrieves a set of ObjectMeta from it. GetBindingInfo does the necessary conversion for us to be able to easily create our Binder (XmlBinder in this case).

Following test shows what we expect from the resolver’s GetBindingInfo method, I expect it to be rather self explanatory:

   1: [TestMethod()]
   2: public void should_transform_metadata_format_into_the_needed_format_for_mef()
   3: {
   4:     ITypeRepository rep = new XmlTypeRepository();
   5:     ConfigValueResolver target = new ConfigValueResolver(rep); // TODO: Initialize to an appropriate value
   6:     IList<ObjectMeta> objectsFromRepository = rep.GetObjectMeta(); // get from xml repository
   7:     IList<BindingInfo> actual;
   8:     actual = target.GetBindingInfo();
   9:     Assert.AreEqual(3, actual.Count);
  10:
  11:     // see if types are registered
  12:     Assert.IsTrue(actual.Any<BindingInfo>(bi => bi.TypeToCompose == typeof(ConsoleOutputter)));
  13:     Assert.IsTrue(actual.Any<BindingInfo>(bi => bi.TypeToCompose == typeof(HelloWorld)));
  14:     Assert.IsTrue(actual.Any<BindingInfo>(bi => bi.TypeToCompose == typeof(Greeter)));
  15: 
  16:     // see if infos set properly
  17:     BindingInfo helloWorld = actual.First<BindingInfo>(bi => bi.TypeToCompose == typeof(HelloWorld));
  18:     BindingInfo consoleOutputter = actual.First<BindingInfo>(bi => bi.TypeToCompose == typeof(ConsoleOutputter));
  19:     BindingInfo greeter = actual.First<BindingInfo>(bi => bi.TypeToCompose == typeof(Greeter));
  20: 
  21:     // for parent type
  22:     Assert.IsTrue(helloWorld.ExportsOfTypeToCompose.Count > 0);
  23:     Assert.IsTrue(helloWorld.ExportsOfTypeToCompose.Any<Type>(t => t == typeof(HelloWorld)));
  24: 
  25:     // verify expectations on injection
  26:     Assert.AreEqual(2, helloWorld.ImportsOfTypeToCompose.Count);
  27:     Assert.IsTrue(helloWorld.ImportsOfTypeToCompose.Any<PropertyInfo>(t => t.PropertyType == typeof(IOutputter)));
  28:     Assert.IsTrue(helloWorld.ImportsOfTypeToCompose.Any<PropertyInfo>(t => t.PropertyType == typeof(IGreeter)));
  29: 
  30:     Assert.AreEqual(2, consoleOutputter.ExportsOfTypeToCompose.Count);
  31:     Assert.IsTrue(consoleOutputter.ExportsOfTypeToCompose.Any<Type>(t => t == typeof(ConsoleOutputter)));
  32:     Assert.IsTrue(consoleOutputter.ExportsOfTypeToCompose.Any<Type>(t => t == typeof(IOutputter)));
  33: 
  34:     Assert.AreEqual(2, greeter.ExportsOfTypeToCompose.Count);
  35:     Assert.IsTrue(greeter.ExportsOfTypeToCompose.Any<Type>(t => t == typeof(Greeter)));
  36:     Assert.IsTrue(greeter.ExportsOfTypeToCompose.Any<Type>(t => t == typeof(IGreeter)));
  37: }

As you see, every exporter needs to export themselves and the mutual contract, that’s why I am checking them with 2. To make this test pass, I came up with the following implementation for the resolver and  its over smart GetBindingInfo:

   1: public class ConfigValueResolver : ValueResolver
   2: {
   3:     ITypeRepository Repository
   4:     {
   5:         get;set;
   6:     }
   7: 
   8:     private IList<ObjectMeta> metaList;
   9:     private IList<ObjectMeta> Objects
  10:     {
  11:         get
  12:         {
  13:             if (metaList == null)
  14:             {
  15:                 metaList = Repository.GetObjectMeta();
  16:             }
  17:             return metaList;
  18:         }
  19:     }
  20:
  21: 
  22:     public ConfigValueResolver(ITypeRepository repository)
  23:     {
  24:         this.Repository = repository;
  25:     }
  26: 
  27:     protected override void OnContainerSet()
  28:     {
  29:         base.OnContainerSet();
  30:         ConfigureContainer();
  31:     }
  32: 
  33:     protected override void OnContainerDisposed()
  34:     {
  35:         base.OnContainerDisposed();
  36:     }
  37: 
  38:     public override CompositionResult<IImportInfo> TryResolveToValue(string name, IEnumerable<string> requiredMetadata)
  39:     {
  40:         CompositionResult<ImportInfoCollection> result = TryResolveToValues(name, requiredMetadata);
  41: 
  42:         return new CompositionResult<IImportInfo>(result.Succeeded, result.Issues, result.Value.First());
  43:     }
  44: 
  45:     public override CompositionResult<ImportInfoCollection> TryResolveToValues(string name, IEnumerable<string> requiredMetadata)
  46:     {
  47:         return TryGetContainerLocalImportInfos(name, requiredMetadata);
  48:     }
  49: 
  50:     private void ConfigureContainer()
  51:     {
  52:         // load up the types and add the binder for them
  53: 
  54:         IList<BindingInfo> bindingList = GetBindingInfo();
  55: 
  56:         foreach (var bindingInfo in bindingList)
  57:         {
  58:             this.Container.AddBinder(new XmlBinder(bindingInfo));
  59:         }
  60: 
  61:
  62:     }
  63: 
  64:     public IList<BindingInfo> GetBindingInfo()
  65:     {
  66:         Debug.Assert(Objects != null);
  67: 
  68:         List<BindingInfo> retVal = new List<BindingInfo>();
  69:         foreach (var objectMeta in Objects)
  70:         {
  71:             IList<Type> exports = new List<Type>();
  72:             exports.Add(objectMeta.ObjectType);
  73:             IList<PropertyInfo> imports = new List<PropertyInfo>();
  74:             //TODO:if imported properties are not in the objects list themselves, it means that they arent exporting anything. 
  75:             // So we can add them safely.
  76:             Debug.Assert(objectMeta.MappingPairs != null);
  77: 
  78:             foreach (var propertyToBeInjected in objectMeta.MappingPairs)
  79:             {
  80:                 // mapping pairs themselves should be in the container in order to be considered to bind
  81:                 Debug.Assert(propertyToBeInjected != null);
  82: 
  83:         retVal.Add(new BindingInfo()
  84:         {
  85:             TypeToCompose = propertyToBeInjected.ConcreteImplementation,
  86:             // exports itsself and its contract
  87:             ExportsOfTypeToCompose = new List<Type>()
  88:             {
  89:                     propertyToBeInjected.ConcreteImplementation,
  90:                     propertyToBeInjected.PropertyToInject.PropertyType
  91:             },
  92:             ImportsOfTypeToCompose = new List<PropertyInfo>(), // currently not implemented
  93:             });
  94:
  95:             imports.Add(propertyToBeInjected.PropertyToInject);
  96:          }
  97:
  98:          retVal.Add(new BindingInfo()
  99:          {
 100:            TypeToCompose = objectMeta.ObjectType,
 101:            ExportsOfTypeToCompose = exports,
 102:            ImportsOfTypeToCompose = imports
 103:           });
 104:         }
 105: 
 106:         return retVal;
 107:     }
 108: }

As you see in the implementation, for every binding info I am adding its Binder. This makes Binder’s implementation on this info relatively straightforward but crucial: It extends the ComponentBinder base class and provides the export info, import info and contract names for the composition operation. Here, I am using the relevantType.ToString() like Jason does in the fluent interface example, but the rest approach is a bit different:

   1: /// <summary>
   2: /// Each XML Binder stands for a type to resolve. 
   3: /// </summary>
   4: /// <remarks>No lifetime supported</remarks>
   5: public class XmlBinder : ComponentBinder
   6: {
   7:     private object instance;
   8:     private static object SyncRoot = new object();
   9: 
  10:     public IList<Type> Exports
  11:     {
  12:         get;
  13:         set;
  14:     }
  15: 
  16:     /// <summary>
  17:     /// List of the properties those are determined to be injected. 
  18:     /// Since the binder is a one-use-only object, setter is private and import list can not be changed during the composition
  19:     /// to synch with the current nature of the container/
  20:     /// </summary>
  21:     /// <value>The imports.</value>
  22:     public IList<PropertyInfo> Imports
  23:     {
  24:         get;
  25:         private set;
  26:     }
  27: 
  28:     /// <summary>
  29:         /// Gets or sets the type of the target resolve type.
  30:     /// </summary>
  31:     /// <value>The type of the resolve.</value>
  32:     public Type TargetResolveType
  33:     {
  34:         get;
  35:         private set;
  36:     }
  37: 
  38:     /// <summary>
  39:     /// Gets the current instance.
  40:     /// </summary>
  41:     /// <value>The current instance, it i singleton for the time being.</value>
  42:     private object CurrentInstance
  43:     {
  44:         get
  45:         {
  46:             if (instance == null)
  47:             {
  48:                 lock (SyncRoot)
  49:                 {
  50:                     if (instance == null)
  51:                     {
  52:                         // a really dummy instance, we can pass take these constructors from the taken types in XML repository
  53:                         // if we want to enable constructor injection. Assuming the type resolved has a default constructor for the time being. 
  54:                         instance = TargetResolveType.GetConstructor(new Type[] { }).Invoke(new object[] { });
  55:                     }
  56:                 }
  57:             }
  58:             return instance;
  59:         }
  60:     }
  61: 
  62:     public XmlBinder(BindingInfo bindingInfo)
  63:     {
  64:         this.Exports = bindingInfo.ExportsOfTypeToCompose;
  65:         this.Imports = bindingInfo.ImportsOfTypeToCompose;
  66:         this.TargetResolveType = bindingInfo.TypeToCompose;
  67:     }
  68: 
  69:     /// <summary>
  70:     /// Gets the export names.
  71:     /// </summary>
  72:     /// <value>The export names.</value>
  73:     public override IEnumerable<string> ExportNames
  74:     {
  75:         get
  76:         {
  77:             return Exports.Select<Type, string>(t => t.ToString());
  78:          }
  79:     }
  80: 
  81:     /// <summary>
  82:     /// Gets the import names.
  83:     /// </summary>
  84:     /// <value>The import names.</value>
  85:     public override IEnumerable<string> ImportNames
  86:     {
  87:         get
  88:         {
  89:             return Imports.Select(info => info.PropertyType.ToString());
  90:          }
  91:     }
  92: 
  93:     /// <summary>
  94:     /// Exports this instance.
  95:     /// </summary>
  96:     /// <returns></returns>
  97:     public override CompositionResult Export()
  98:     {
  99:         foreach (var type in Exports)
 100:         {
 101:             AddValueToContainer(type.ToString(), CurrentInstance);
 102:         }
 103: 
 104:         return CompositionResult.SucceededResult;
 105:     }
 106: 
 107:     /// <summary>
 108:     /// Imports the specified changed value names.
 109:     /// </summary>
 110:     /// <param name=”changedValueNames”>The changed value names, not really used.</param>
 111:     /// <returns></returns>
 112:     public override CompositionResult Import(IEnumerable<string> changedValueNames)
 113:     {
 114:             foreach (var info in Imports)
 115:             {
 116:                 CompositionResult<object> component = Container.TryGetBoundValue(info.PropertyType.ToString(), info.PropertyType);
 117:                 // do the injection. Currently assuming that only non-indexed values are to be resolved
 118:                 if (component.Succeeded)
 119:                 {
 120:                     info.SetValue(CurrentInstance, component.Value, null);
 121:                 }
 122:                 else
 123:                 {
 124:                     throw new InvalidOperationException(component.Issues[0].Description, component.Issues[0].Exception);
 125:                 }
 126:
 127:             }
 128: 
 129:             return CompositionResult.SucceededResult;
 130:         }
 131: 
 132:     public override bool Equals(object obj)
 133:     {
 134:         XmlBinder binder = obj as XmlBinder;
 135:         if (binder != null)
 136:         {
 137:             return binder.TargetResolveType == this.TargetResolveType;
 138:         }
 139:         return false;
 140:     }
 141: }

And now we have done all the dirty infrastructure work. Those was all for this test to pass:

   1: [TestMethod]
   2: public void should_print_hello_world_to_console()
   3: {
   4:     ConfigValueResolver resolver = new ConfigValueResolver(new XmlTypeRepository());
   5:     //IOutputter outputter = null;
   6:     //IGreeter greeter = null;
   7:     HelloWorld helloWorld = null;
   8:     try
   9:     {
  10:         CompositionContainer container = new CompositionContainer(resolver);
  11:         container.Bind();
  12:         helloWorld = container.TryGetBoundValue<HelloWorld>().Value;
  13:     }
  14:     catch (CompositionException ex)
  15:     {
  16:         foreach (CompositionIssue issue in ex.Issues)
  17:         {
  18:             Console.WriteLine(“issue = {0}”, issue.ToString());
  19:         }
  20:     }
  21:
  22:     Assert.IsNotNull(helloWorld);
  23:     Assert.IsNotNull(helloWorld.Outputter);
  24:     Assert.IsNotNull(helloWorld.Greeter);
  25:
  26:     helloWorld.SayIt();
  27: }

Ignore the try catch, that’s because of the *damn* error handling mechanism of MEF depending on the issues and not providing a concatenated representation of the error message. At the end, dependencies are injected, “hello world” is printed to the test console, and the world is a better place to live. Thank you all !

You can download the sources from here, I have %80 test coverage now. Any comments, criticisms, cheques with a lot of trailing zeros well appreciated as always.
kick it on DotNetKicks.com

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

Exploring MEF Extensibility Points

July 4th, 2008 by Sidar Ok

After I had a chance to dance with MEF, I wanted to go a step further and create my own logic to Bind the dependencies, and integrate it to the existing composition system. I have to say that, oh god, it was NOT as easy that as I expected. Current nature of the APIs  heavily depend  on counter intuitive usage. Again, I am having a difficult time to save my critics as a separate post as you can see :)

There are currently 2 main extensibility points in MEF. Custom Binders and Value Resolvers.

Custom Binders

The current nature of the Composition Container is, basically, Container is the god. It needs to have everything to bind, if you want to add a type binding logic, you are welcome. But first, you need to add your type to the container. Well, that’s a fair game, since our logic is Binding(wiring really) logic - not a type or instance management one. This means that we have to write the following as usual:

   1: CompositionContainer container = new CompositionContainer();
   2: container.AddComponent<Consumer>(consumer);
   3: container.AddComponent<Provider>(provider);
   4: container.Bind();

Where Provider and Consumer are just defined with Export & Import model as MEF needs them :

   1: public class Consumer
   2: {
   3:     [Import(typeof(IProvider))]
   4:     public IProvider Provider
   5:     {
   6:         get;
   7:         set;
   8:     }
   9:
  10:     public Consumer()
  11:     {
  12:
  13:     }
  14:
  15:     public int GetAnInteger()
  16:     {
  17:         return this.Provider.GetAnInteger();
  18:     }
  19:
  20: }

And hence is the provider:

   1: [Export(typeof(IProvider))]
   2: public class FavoredProvider : IProvider
   3: {
   4:     #region IProvider Members
   5:
   6:     public int GetAnInteger()
   7:     {
   8:         return 5;
   9:     }
  10:
  11:     #endregion
  12: }

And this makes the following test to pass, which just expects the hard coded “5″ value to be returned:

   1: /// <summary>
   2: ///A test for GetAnInteger
   3: ///</summary>
   4: [TestMethod()]
   5: public void GetAnIntegerTest()
   6: {
   7:        Consumer target = new Consumer();
   8:        CompositionHelper.InitializeContainerForConsumer(target); // this is where container configuration goes
   9:        int expected = 5;
  10:        int actual;
  11:        actual = target.GetAnInteger();
  12:        Assert.AreEqual(expected, actual);
  13: }}

Now, let’s come up with a hypothetical scenario : We need the same instance for every consumer (singleton). How hypothetical that is for a DI container! So  while configuring I would expect to write something close to the following, and still expect test to pass! (Note that you can use IsSingleton for the contract, but the one and only life time controlling mechanism isn’t singleton is it? ;) )

   1: CompositionContainer container = new CompositionContainer();
   2: var myVeryCustomBinder = new SampleBinder();
   3: container.AddComponent<Consumer>(consumer);
   4: // not adding the provider exlusively, expecting the binder to handle
   5: container.AddBinder(myVeryCustomBinder);
   6: container.Bind();

Q: So we didn’t add the provider to the container, haven’t you just said that this is a deal breaker ?

A: Yes it is, you are right. My test now breaks. But I can make that up, in my custom binder. Gimme a break.

To write a custom binder I need to inherit from the abstract class ComponentBinder . In ComponentBinder, there are several virtual methods that are waiting to be overridden depending on my logic:

  1. public override CompositionResult Export() : This is the place that we’ll add the container the results of our resolve operations. The return value also indicates whether the operation is succeeded or not.
  2. public override CompositionResult Import(IEnumerable<string> changedValueNames) : And this is the place that we will retrieve the demanding objects for the services that are exported.
  3. public override CompositionResult BindCompleted() : This kind of acts as an event, (why is it not one?) and will be called when the binding is completed. Here you can do your sanity checks after your bind operations needed for your binder,
  4. public override IEnumerable<string> ExportNames ; These are the “names” for the types. This can be the name specified in the Export() declaration in the attribute or a default one.
  5. public override IEnumerable<string> ImportNames : Same goes with imports, but instead import process.

So here would be my Custom Binder:

   1: public class SampleBinder : ComponentBinder
   2: {
   3:     private FavoredProvider ProviderToInject
   4:     {
   5:         get;
   6:         set;
   7:     }
   8:
   9:     private static readonly object syncRoot = new object();
  10:
  11:     public SampleBinder()
  12:     {
  13:         if (ProviderToInject == null)
  14:         {
  15:             lock (syncRoot)
  16:             {
  17:                 ProviderToInject = new FavoredProvider();
  18:             }
  19:         }
  20:     }
  21:
  22:     public override CompositionResult Export()
  23:     {
  24:
  25:         this.AddValueToContainer(CompositionServices.GetContractName(typeof(IProvider)), this.ProviderToInject, “Provider”);
  26:         return CompositionResult.SucceededResult; ;
  27:     }
  28:
  29:     public override CompositionResult Import(System.Collections.Generic.IEnumerable<string> changedValueNames)
  30:     {
  31:         return base.Import(changedValueNames);
  32:     }
  33:
  34:     public override CompositionResult BindCompleted()
  35:     {
  36:         return base.BindCompleted();
  37:     }
  38:
  39:     public override IEnumerable<string> ExportNames
  40:     {
  41:         get
  42:         {
  43:             return base.ExportNames;
  44:         }
  45:     }
  46:
  47:     public override IEnumerable<string> ImportNames
  48:     {
  49:         get
  50:         {
  51:             return base.ImportNames;
  52:         }
  53:     }
  54:
  55: }

As you see, we are not doing anything on import. For any import of I provider type, we Are providing  the Favored Provider.  Also notice the badly named utility class CompositionServices which currently only has 1 method, and it is a useful one : GetContractName. Without this, I’d have to hardcode it or get it with a drop of reflection magic.

Adding this Binder Makes my test pass, and I am happy.

Value Resolvers

This is an enabled model in this CTP, but the Usage of it is not enabled (at least I couldnt find out a way, since the Resolver value in the container does not have a setter - any feedback on this appreciated(1)) . Value Resolver is the part to provide the types, and probably in a sane implementation life time logic will go here. It is an abstract class and 2 abstract methods are waiting to be overriden, below is a sample Value Resolver:

   1: public class CustomValueResolver : ValueResolver
   2: {
   3:     public override CompositionResult<IImportInfo>
   4: TryResolveToValue(string name, IEnumerable<string> requiredMetadata)
   5:     {
   6:         // do your resolve, and send it back   
   7:         ImportInfo<FavoredProvider> resolvedValue =
   8:             new ImportInfo<FavoredProvider>(null);
   9:         return new CompositionResult<IImportInfo>(true,
  10:             Enumerable.Empty<CompositionIssue>(), resolvedValue);
  11:     }
  12:
  13:     public override CompositionResult<ImportInfoCollection>
  14: TryResolveToValues(string name, IEnumerable<string> requiredMetadata)
  15:     {
  16:     // do the same if you have more than one service to provide to one consumer
  17:         ImportInfo<FavoredProvider> resolvedValue =
  18:             new ImportInfo<FavoredProvider>(null);
  19:
  20:         return new CompositionResult<IImportInfo>(true,
  21:             Enumerable.Empty<CompositionIssue>(), resolvedValue);
  22:     }
  23: }

In the future hopefully we will be able to create our own component catalogs and associate resolvers to them, like the way we can’t to now to both Container and to AssemblyComponentCatalog.(2)

Hope this article gave a deeper hint on what’s going on MEF side of things. Any comments on this are welcome as always.

 (1): Jason pointed out that there is an overload of CompositionContainer, that takes ValueResolver as a parameter. doh! (see comments)

(2): Still couldnt find a way of doing the same to Component Catalog.

kick it on DotNetKicks.com

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

Managed Extensibility Framework (MEF) at a Glance

June 16th, 2008 by Sidar Ok

After Krysztof Cwalina has announced Microsoft’s plans on releasing extensible features to .NET framework, the CTP of MEF has made its way too quick into the market. As a result of this, we have an immature .DLL called ComponentModel.dll born into our hands, with being far from complementing the community’s needs and lacking lots of features & architectural concerns – and of course you know it, with nearly no xml comments and not very informative error messages.

But it is still CTP, and that’s what a CTP is for. Criticism against it is a matter of another post; but as .NETters we need to know about this vibe coming because this young baby is going to be a part of the core framework and one day, with an update, will be pushed to x million of computers.

So I better stop judging for the time being and let’s get our hands dirty with what we have currently as early adopters.

Dependency Injection with Management Extensibility Framework

In the dll, there are 2 main namespaces coming: System.ComponentModel.Composition and System.Reflection.StructuredValues . So as you see, to do its magic MEF uses reflection. This also means that one can define contracts using hard coded strings instead of a strongly typed contract. In the examples those are shipped with MEF, you can see this usage, but I think everybody will agree that this is not a good practice. So let’s see how we can build a strongly typed and contract based dependency injection mechanism.

So let’s get to define a very simple contract:

   1: /// <summary>
   2: /// Contract for retrieving pretty dummy data
   3: /// </summary>
   4: public interface IDataRetriever
   5: {
   6:     /// <summary>
   7:     /// Gets the sample data.
   8:     /// </summary>
   9:     /// <param name=”count”>The count.</param>
  10:     /// <returns></returns>
  11:     IEnumerable<ExampleData> GetSampleData(int count);
  12: }

This expects to get a list of example data #count times. ExampleData is a Poco, and its structure contains just a string key:

   1: /// <summary>
   2: /// Model for Sample Data
   3: /// </summary>
   4: public class ExampleData
   5: {
   6:     /// <summary>
   7:     /// Gets or sets the data key.
   8:     /// </summary>
   9:     /// <value>The data key.</value>
  10:     public string DataKey
  11:     {
  12:         get;
  13:         set;
  14:     }
  15: }

So we expect from this method to return a list of ExampleData , with their DataKey field populated by their indexes. So here is the test that ensures this basic expectation:

   1: /// <summary>
   2: ///A test for GetSampleData
   3: ///</summary>
   4: [TestMethod()]
   5: public void GetSampleDataTest()
   6: {
   7:     IDataRetriever target = new DataRetriever();
   8:     int expectedCount, count;
   9:     expectedCount = count = 10;
  10:
  11:     IEnumerable<ExampleData> actual = target.GetSampleData(count);
  12:     Assert.AreEqual(expectedCount, actual.Count<ExampleData>());
  13:
  14:     IEnumerator<ExampleData> enumerator = actual.GetEnumerator();
  15:     int expectedKey = 0;
  16:     while (enumerator.MoveNext())
  17:     {
  18:         Assert.IsNotNull(enumerator.Current);
  19:         Assert.AreEqual(enumerator.Current.DataKey, expectedKey.ToString());
  20:         expectedKey++;
  21:     }
  22: }

And after a couple of failures (yes, even in this simplicity I manage to fail), here is the implementation that passes this test:

   1: [Export(typeof(IDataRetriever))]
   2: public class DataRetriever : IDataRetriever
   3: {
   4:     #region IDataRetriever Members
   5:
   6:     //[Export(”Retriever”)]
   7:     public IEnumerable<ExampleData> GetSampleData(int count)
   8:     {
   9:         List<ExampleData> retVal = new List<ExampleData>(count);
  10:         for (int i = 0; i < count; i++)
  11:         {
  12:             yield return new ExampleData()
  13:             {
  14:                  DataKey = i.ToString()
  15:             };
  16:         }
  17:     }
  18:
  19:     #endregion
  20: }

Now, the syntax of MEF needs us to shout what we have, and explicitly define by attributes what we want to expose as our services to be injected (intrusive, girrrr…) And since there is an exporter, there should be an importer too, which is a page in this scenario. Beware, the page is using this interface and it is marked as public, as MEF can inject only public dependencies choosing the same way as the many of the other IOC containers in the wild.

   1: [Import(typeof(IDataRetriever), IsOptional = false)]
   2: public IDataRetriever Retriever
   3: {
   4:   get;
   5:   set;
   6: }

Note that these Import and Export attributes are under System.ComponentModel.Composition namespace and they both have another overload that takes strings as contract names instead of contract types as shown above.

Please also note that as a client to DataRetriever, this page doesn’t know any bit about which implementation of IDataRetriever that it will retrieve (DI mission accomplished). So in which house is all the party happening? I placed an initialization code inside the page constructor:

   1: public _Default()
   2: {
   3:     DataRetrieverHelper.InitializeContainer<_Default>(this);
   4: }

And this helper is a very smart guy who knows about everything about this magic (so from what we learnt from Italian mafia movies, it should be killed – by a DSL or an XML configuration. But MEF doesn’t support it currently out of the box – but with a bit of a hack it can be done):

   1: public static class DataRetrieverHelper
   2: {
   3:     public static void InitializeContainer<T>(T toFillDependency)
   4:         where T:class
   5:     {
   6:         CompositionContainer container = new CompositionContainer();
   7:         container.AddComponent<T>(toFillDependency);
   8:         container.AddComponent<DataRetriever>(new DataRetriever());
   9:         container.Bind();
  10:     }
  11: }

As you see, you add the consumer, add the service, and call bind – MEF container cares the rest.

Of course, the first question that is expected after how, is what if we need to add another implementation which is a very likely scenario? For e.g what if we have 2 implementations of the contract, say to return a list of keys in reverse order and the normal one, which one is the container going to choose to bind?

Handling Multiple Exports Within the Container

Well, since the requirements are extended, we need to write another test for the new requirement:

To pass this test, the implementation is trivial:

   1: /// <summary>
   2: ///A test for GetSampleData
   3: ///</summary>
   4: [TestMethod()]
   5: public void GetSampleDataReverseTest()
   6: {
   7:     IDataRetriever target = new DataRetreiverReverse();
   8:
   9:     int expectedCount, count;
  10:     expectedCount = count = 10;
  11:
  12:     IEnumerable<ExampleData> actual = target.GetSampleData(count);
  13:     Assert.AreEqual(expectedCount, actual.Count<ExampleData>());
  14:
  15:     IEnumerator<ExampleData> enumerator = actual.GetEnumerator();
  16:     int expectedKey = count - 1;
  17:     while (enumerator.MoveNext())
  18:     {
  19:         Assert.IsNotNull(enumerator.Current);
  20:         Assert.AreEqual(enumerator.Current.DataKey, expectedKey.ToString());
  21:         expectedKey–;
  22:     }
  23: }

It is obvious that if we don’t change the helper class which does the magic, we won’t get the new implementation. So let’s add it by using AddComponent generic method :

   1: public static void InitializeContainer<T>(T toFillDependency)
   2:     where T:class
   3: {
   4:     CompositionContainer container = new CompositionContainer();
   5:     container.AddComponent<T>(toFillDependency);
   6:     container.AddComponent<DataRetriever>(new DataRetriever());
   7:     container.AddComponent<DataRetreiverReverse>(new DataRetreiverReverse());
   8:     container.Bind();
   9: }

Ok, let’s run the application, and face a very nice error message:

“There was at least one composition issue of severity level ‘error’. Review the Issues collection for detailed information”

“WTF is issues collection?” were the first words out of my mouth unfortunately :) . The exception we get here is a System.ComponentModel.Composition.CompositionException and the “issues” is the Issues property of the exception we are getting. This is a collection of System.ComponentModel.Composition.CompositionIssue object, and their Description field is a string that has the meaningful explanation of what’s happening. In the list I got there was 2 issues that we were already expecting:

  1. “Multiple exports were found for contract name ‘MEFSample.Interfaces.IDataRetriever’. The import for this contract requires a single export only.”
  2. “A failure occurred while trying to satisfy member ‘Retriever’ on type ‘default_aspx’ while trying to import value ‘MEFSample.Interfaces.IDataRetriever’. Please review previous issues for details about the failure.”

Apart from not getting the exceptions in the first go, and ignoring the first message is cryptic, well, this is nice. Theoretically I can see all the errors happened during the build up process, not get stuck in the first one.

Back to the game, now I have 2 implementations in the container, I need a mechanism to choose between two – There is where this System.ComponentModel.Composition.ImportInfoCollection comes into the game. This collection holds a list of ImportInfo objects, which are basically information about the injected members, nothing more. Now, the new property will go as follows:

   1: [Import(typeof(IDataRetriever), IsOptional = false)]
   2: public ImportInfoCollection<IDataRetriever> ResolvedDependencies
   3: {
   4:     get;
   5:     set;
   6: }

When “Bind” is called, this property will be filled automatically instead of the old one. So now I have a list, I am able to decide between the resolved dependencies. Here is my new Retriever property:

   1: public IDataRetriever Retriever
   2: {
   3:    get
   4:    {
   5:        return ResolvedDependencies[0].GetBoundValue();
   6:    }
   7: }

Here I am choosing the first one; I can choose the 2nd one as well since Resolved Dependencies collection will have 2 values.Okay, [0] seems a cumbersome way of selecting the “correct” one, admitted :). Frankly, MEF team included the mechanism in this CTP so we can also specify metadata information along with the injected interfaces, which will help us to be able to decide better what implementation to choose in the run time. But this post got long so I hopefully throw another post to explore what we can do within MEF boundaries.

You can download the sources by clicking here.

kick it on DotNetKicks.com

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

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();
   8: 
   9:   string testVar = “the variable to be tested”;
  10:   string expectedVar = “TheVariableToBeTested”;
  11:
  12:   string resultVar = strategy.ConvertString(testVar);
  13: 
  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
   7: 
   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);
  17: 
  18:         // trivial example, not considering edge cases.
  19:         string retVal = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(toApplyNaming);
  20:         return retVal.Replace(” “, string.Empty);
  21:     }
  22: 
  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();
   8: 
   9:     container.RegisterType<INamingStrategy, PascalNamingStrategy>(); //we will abstract this later 
  10: 
  11:     INamingStrategy strategy = container.Resolve<INamingStrategy>();
  12: 
  13:     Assert.IsNotNull(strategy, “strategy injection failed !!”);
  14:     Assert.IsInstanceOfType(strategy, typeof(PascalNamingStrategy), “Strategy injected, but type wrong!”);
  15: 
  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();
   8: 
   9:    container.RegisterType<INamingStrategy, PascalNamingStrategy>(); //we will abstract this later 
  10: 
  11:    // notice that we dont know what strategy will be used, and we dont care either really
  12: 
  13:    INamingStrategy strategy = container.Resolve<INamingStrategy>();
  14: 
  15:    string testVar = “the variable to be tested”;
  16:    string expectedVar = “TheVariableToBeTested”;
  17:    string resultVar = strategy.ConvertString(testVar);
  18:
  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 DotNetKicks.com


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