Tuesday, January 26, 2010

Making Part Declarations Easier with InheritedExports

After playing around with MEF for a while, you begin to find more and more locations where it could be used to extend your application.  It works great for a large number of scenarios and provides a method for others to extend your apps in a way as simple or complex as you want to make it for them.  However, anyone who has sought community participation can tell you that the best way to get such is to make thing as easy as possible for a member of the community to participate.  If you have the greatest, extensible application in the world but require 50 steps to get a part added to the application, the user community may not be very prone to build extensions for such.  Alternatively, if the work required to extend the application was whittled down to only a few steps, the probability of participation rises.  In this blog post, we'll look at this pattern and show how using MEF's InheritedExport attribute can be used to make part creation extremely simple for their authors.

Reviewing Previous Examples:

In previous examples of this series, we created parts that would be placed into a directory and imported into the app based on how the classes were decorated.  By explicitly decorating our parts with the Export attribute works well since it gives us the ability to say which classes to import and which not to; however, in order to use the Export attribute we also had to include a reference to the System.ComponentModel.Composition assembly & namespace.  Depending on how we setup our part contacts, we would also need to add a reference to our application as well.  While that's not a lot of setup, it adds up since it has to be done every time a new part has to be created.  If the parts were created as part of a framework or engine, then it would be in a person's best interest to create a VS template or some other form of code generation or snippets to automate as much of that ceremony as possible.  But what if there was a simpler way to address this from within the application we're trying to extend?

Simplification through Inherited Exporting:

One of the lesser-documented items contained within MEF is the InheritedExport attribute.  This attribute flags all derived classes as parts that fit the contract defined by it.  So instead of requiring every part that implements a particular interface or base class to use the Export attribute and settings, you can just decorate the interface or base class with the InheritedExport attribute and then every class is considered to be an Exported part by default.  If you are familiar with WCF, this is similar to the practice of creating an Interface for declaring your data contracts instead of directly decorating concrete classes.  Below is an comparison between the way that has been show thus far and using the InheritedExport attribute.

Previous Example:

   1:  [Export("commands", typeof(ICommand))]
   2:  public class Command1 : ICommand
   3:  {
   4:      // Implementation of the Interface
   5:  }
   6:   
   7:  [Export("commands", typeof(ICommand))]
   8:  public class Command2 : ICommand
   9:  {
  10:      // Implementation of the Interface
  11:  }

Inherited Example:

   1:  [InheritedExport("commands",typeof(ICommand))]
   2:  public interface ICommand
   3:  {
   4:      // Interface Declaration
   5:  }
   6:   
   7:  public class Command1 : ICommand
   8:  {
   9:      // Implementation of the Interface
  10:  }
  11:   
  12:  public class Command2 : ICommand
  13:  {
  14:      // Implementation of Interface
  15:  }

Without the requirement of marking all of the parts with the Export attribute, the developers who are creating extensible parts for your application will no longer need to reference the System.ComponentModel.Composition namespace.  In addition, the risk of mistyping the contract information in the Export attribute is removed.  By using the InheritedExport attribute, the only requirement for authoring parts becomes just a reference to the assembly containing the decorated base class or assembly.

A Useful Pattern of Inherited Exporting:

While the InheritedExport attribute provides a simplified and safer method of handling part creation, it is an All-or-Nothing mechanism.  While there are ways to exclude parts using different catalogs, there is no way to explicitly exclude a part like you could when we were using the Export attribute on all parts.  A good way around this issue is to base your part contract/type on an interface and add the InheritedExport attribute to an abstract base class that implements said interface.  This provides the blanketed support and convenience of using InheritedExport while providing authors an advanced mechanism by directly implementing the interface and adding the Export attribute manually if needed.  Below is an example of this pattern.

   1:  public interface ICommand
   2:  {
   3:      // Interface Declaration
   4:  }
   5:   
   6:  [InheritedExport("commands", typeof(ICommand))]
   7:  public abstract class CommandBase : ICommand
   8:  {
   9:      // Abstract implementation of the Interface
  10:  }
  11:   
  12:  public class Command1 : CommandBase
  13:  {
  14:      // Implementation of the Abstract Class
  15:  }
  16:   
  17:  public class Command2 : CommandBase
  18:  {
  19:      // Implementation of the Abstract Class
  20:  }

Summary:

In this post, we looked at how to streamline and simplify our part definitions by using the InheritedExport method instead of just the Export attribute.  We looked at the benefits of this simplicity and how it can help make things easier for part authors as well as identified a possible fault with using the InheritedExport attribute at the wrong level of abstraction.  In the corresponding example project linked below, the concepts discussed above are applied to a previous example project in order to illustrate some of the simple benefits that can be used within your application.

Resources:

kick it on DotNetKicks.com Shout it

Tuesday, January 12, 2010

A Configurable Type Catalog for MEF

Over the past month or so, I've had  some time to focus on a few different projects.  In one of these new projects, I was using MEF in order to provide a number of extensibility points.  Everything was going well until I started to dive into a place where I wanted it to be extensible but also configurable like a traditional provider model scattered throughout the .Net framework. With MEF, there's a couple of different ways of handling this situation; however, after playing around with a few of them, I decided to extend the TypeCatalog in order to provide another layer of abstraction that allows me to harness the power of MEF with the ability of outside configuration. In this article, we'll diving into the code that provides provider-like configuration aspects to MEF as well as shine the light at 2 possible pitfalls of using something like this.  Before we do that though, let's examine what MEF has to offer out of the box in order to understand why I felt another layer was needed for my project.

Looking in the Box and at MEF-Contrib

So far in my MEF posts, I've really been focused on simple solutions that utilize the AssemblyCatalog and DirectoryCatalog objects.  These specific catalogs provide a very fast and easy way of composing your various parts together. Part of their simplicity comes from how they handle the parts that it finds in the assemblies you provide it; namely, they take an All-or-Nothing approach.  If they find parts that meet the defined contract criteria, they assume that they are going to be part of some composition.  But what if you only wanted to use only a few parts located in a loaded assembly? 
This question was half of the problem I was trying to solve for my project.  Looking around what's been done so far with MEF, I saw that I could address this part of my problem using a TypeCatalog.  A TypeCatalog differs from other ComposablePartCatalogs in that it allows you to explicitly specify which Types you want to use as Parts.  For example, in previous posts we showed "Help Text" of various parts that represented different commands/arguments of a command line application.  If you didn't want Command #2, you could simply load all other commands into a collection explicitly and then pass the collection into a TypeCatalog.
Great, one problem solved, right?  I can now explicitly load which parts I want to import; however, the second part of my problem was that I didn't want to recompile  the code every time I wanted to change which parts were imported.  At this point, I started to look around at what other people might have already done that would allow this type of configuration.  I ended up looking at the Provider Model for MEF that was a part of the MEF-Contrib project out on CodePlex. What the Provider Model from MEF-Contrib does is move the part declarations (i.e. the Import and Export Attributes) to a custom configuration section.  This held a lot of promise; however, ran into some trouble while working with it.  After about a day of working with the MEF-Contrib provider model, I decided to try my hand at a different approach.

Adding a Layer on top of MEF

While I'm still determined to look into the MEF-Contrib provider model deeper in the near future, I also began to feel that mixing the attributed model and a provider model in the same application felt a bit dirty or smelly. I wanted the leverage the power and simplicity MEF's attributed model but be able to push it to the level of configuration that comes with a provider model.  In order to reach this goal, I decided to add another layer of abstraction onto of the great foundation MEF provides for extensibility.
In order to do this, I needed 2 things:
  1. A Custom Configuration Section to Identify the specific Types to import
  2. A ComposablePartCatalog that will grab these parts.

Creating the Configuration Section

I'm not going to go into a large amount of information on how to create a custom configuration section.  There's a large amount of resources out on the Internet that can assist with such.  What I needed was a simple section that took a collection of types.  I wanted to truly keep things simple.  What came out mapped to the following:
1:  <configuration>
2:      <configSections>
3:          <section
4:            name="mef.configurableTypes"
5:            type="MEFExample8.Core.Provider.ConfigurableTypeSection, MEFExample8.Core" />
6:      </configSections>
7:   
8:      <mef.configurableTypes>
9:          <parts>
10:              <part type="MEFExample8.TestCommand1, MEFExample8" />
11:              <part type="MEFExample8.Commands.TestCommand3, MEFExample8.Commands" />
12:          </parts>
13:      </mef.configurableTypes>
14:  </configuration>


Creating the Catalog

Now that I have the section how I needed it, I had to create a catalog that will utilize it.  While I could have create a custom catalog using the ComposablePartCatalog base class, I decided to just extend the TypeCatalog that comes with MEF.  The TypeCatalog works great for such and the only thing I had to do was bring in the Types from the config file, load them into an IEnumerable<Type> collection, and then pass it to the TypeCatalog base.  Simple right?
As it turned out, I looked beyond my original needs and found two issues.  The first was addressing what to do if the configuration section was named differently.  The second issue was dealing with what to do if the catalog is instantiated more than once.  Luckily, a simple solution to both was to allow the developer to pass in the section name into the catalog's constructor.  This addressed the renaming concern while allowing multiple catalogs to point to different configuration sections.
Below is the catalog's code:
1:  public class ConfigurableTypeCatalog : TypeCatalog
2:  {
3:      public ConfigurableTypeCatalog()
4:          : base(GetTypes())
5:      {
6:      }
7:   
8:      public ConfigurableTypeCatalog(string sectionName)
9:          : base(GetTypes(sectionName))
10:      {            
11:      }
12:   
13:      private static IEnumerable<Type> GetTypes()
14:      {
15:          return GetTypes("mef.configurableTypes");
16:      }
17:   
18:      private static IEnumerable<Type> GetTypes(string sectionName)
19:      {
20:          var config = GetSection(sectionName);
21:   
22:          IList<Type> types = new List<Type>();
23:   
24:          foreach (ConfigurableTypeElement p in config.Parts)
25:          {
26:              types.Add(Type.GetType(p.Type));
27:          }
28:   
29:          return types;
30:      }
31:   
32:      private static ConfigurableTypeSection GetSection(string sectionName)
33:      {
34:          var config = ConfigurationManager.GetSection(sectionName) as ConfigurableTypeSection;
35:   
36:          if (config == null)
37:          {
38:              throw new ConfigurationErrorsException(string.Format("The configuration section {0} could not be found.", sectionName));
39:          }
40:   
41:          return config;
42:      }
43:  }

As I stated before, I decided to extend the TypeCatalog class. In order to extend it and meet the needs of my project, I overloaded the constructor so that I could set the default configuration section name (used in the configuration file snippet above) while allowing the second constructor to specify the section name.  Since the constructor of the TypeCatalog class takes either a single Type or a collection of Types, I turned the code that retrieves that information from the configuration section into a static value.  Since I'm not overriding any aspects of the TypeCatalog other than the constructors, I needed a way to pass the information to it as such and the static methods provided.

Notes about the Catalog:

At this point, I have a fully functional catalog that allows me to specify which types to include into a certain piece of my application. After I played around with it a bit I found that it worked well but had a few shortcomings that may cause people to wonder what's going on.
The first scenario I came across was working with the catalog to reference parts in a subdirectory.  This issue doesn't exist if the types you are referencing are in the same assembly or an assembly that's in the same directory as the executing program; however, if the assembly is in a subdirectory, you'll need to probe the directory as described in my previous MEF post - Using MEF and Custom Configuration Sections.
The second scenario came with the need for Type or Part exclusions.  The code above uses the same attributed model that all out of the box catalogs use.  This means that if you created an assembly with 3 attributed parts in it and used an AssemblyCatalog or similar one, all 3 parts would be identify and consumed.  The custom catalog outlined in this post focuses on Type inclusion and not exclusions. Because of this, if the above catalog is combined in an AggregateCatalog, all of the parts that meet the contract will still be imported.  Through this fact, I highly recommend using the above catalog separately from the others.

So What's Next?

As for this catalog, I need to do a bit more refining and possibly add a few more catalogs that follow a similar manner.  Ultimately, I'm going to be wrapping some unit tests around it and packaging it up separately.  Beyond that, there's a lot of MEF content coming in the future so stay tuned.

Resources:


kick it on DotNetKicks.com Shout it

Wednesday, January 6, 2010

Goals for the New Year (2010 ed.)

When I started to write down my professional goals for 2010, I ended up doing the same things as I did last year; just create a list of things to learn.  Looking back over my experiences while attempting to accomplish my goals for 2009, I began to believe that this was the wrong approach.  My initial goals were very focused on learning different technologies or hitting certain milestones in general.  By the end of 2009, I found that sure I may have hit most of my goals; however, something was lacking.

For example, one of the items that I completely wasn't anticipating becoming so passionate about was the possibilities of MEF.  This lead to a large number of rapid fire posts in March on some pretty rudimentary tutorials on the basics of MEF.  While I was working on creating these tutorials, I constantly wished I was able to work on the latter posts (the ones that I'm slowly working on currently).  It wasn't because I didn't think providing tutorial information wasn't important but being able to provide a better context was.  This was also true earlier in the year during my initial F# exploits.  Doing tutorials is good but sometimes showing the overall value before the tutorials can provide the basis as to the WHY someone can learn something instead of just the HOW to use it.  If you have ever looked into becoming a better speaker, this practice is sometimes described as "showing the sex first".  Get a person interested and intrigued first and then provide them the information and tools necessary to run with what you showed.

With this in mind, it's what my goals now resolve around.  While I'll be working hard on learning new technologies or tying down loose ends on technologies I haven't fully learned, my focus is going to be on context.

Things I'm focusing on in 2010:

Getting More Involved
I'm a firm believer that teaching is one of the greatest ways of evaluating how well you know a topic. One of the things I discovered a few years back is a passion for presenting and teaching. Combine that with a desire to get more involved in the development community as a whole and it leads to a lot of opportunities.  Right now I'm staring at about 4-5 presentations just in the first half of the year to various user groups and code camps all over the midwest.  I'm hoping to expand this more by the end of the year.  Sure it'll keep me busy and traveling but it's fun and I would am looking forward to meeting a lot of the community leaders at each location.  As my calendar solidifies, I'll make sure to update things here.

More Contextual Value on Posts
Looking over the past 2-3 years that I've been writing in this blog, the posts that have the deepest impact are also the ones that provide the richest examples or specific focus.  Some of the basic tutorial posts have appeared to be viewed well; however, the some of the posts that took me a significantly longer amount of time to write and develop the samples for have seen the best amount of feedback.  With this in mind, I'm going to focusing more on intermediate examples more than introductory posts.  The introductory elements will still remain; however, I'm hoping to change the quantity of the two types of posts in order to provide more balance and value to the readers.

Tying up Loose Ends
Last year I worked a lot on learning a number of new tools; however, some of them I only learned enough to understand where they may fit into my current situation (a.k.a. just learning what value is in it for me).  This is usually a pretty good way of learning things; however, it can limit the potential. After changing jobs at the end of 2009, being able to reevaluate what I learned last year and expand on such will allow me to adapt better to different scenarios.  This also will help me provide even better context when learning other things. An example of this is the fact that while I know the basics of writing in Silverlight, I need a little bit deeper understanding of it so that I can start applying MEF into my Silverlight applications when applicable.

Redefining a Dream
When I started getting serious about my development career, I wondered what I would consider to be my dream job.  This idea always shifted with every career progression on my way towards my dream job.  Recently, I landed a job that is the closest match thus far and am begin to evaluate the environments and companies I've worked for thus far as well as my current one.  While I don't plan on leaving my current employer since I just came onboard and they are a very good company thus far, I'm a person that loves striving for what's next. Perhaps what's next is not a different company but something that augments my day job like getting more involved. Perhaps is back to a more remote working environment.  Lots of ideas to consider and think about.  Ultimately though, it's the journey that drives me, not what I have currently obtains. Anything is possible as long as you keep dreaming in my opinion.

Wednesday, December 30, 2009

Controlling Personal Projects with TDD/BDD

Last night, a friend and I were discussing our ever growing list of personal projects and tasks that we strive to find/make time to whittle away. The items on our list ranged from reading a simple blog post, asking a mentor a question, or working on a personal, pet project. I don't know any developer who doesn't have a similar list to be honest.

Though the conversation, we began to talk about an issue we were both sharing about our pet projects getting drawn out. While there are true reasons (i.e. time constraints being the most prevalent), the one that plagued us was the concept of scope creep. As a developer, we battle with scope creep during our day jobs (usually) but to experience such at home leads to only a single person to put the blame on; ourselves.

This really got me thinking and reflecting on my project and my own scope creep issues. I began to realize that every time I had scope creep, it was a spot where I hadn't written unit tests first. In many cases I focus on a test-first strategy of TDD; however, there are a few times when I get in the flow and just write the code. This works sometimes but the times in which I can identify as scope creep all fell into these moments. If I had stayed focus on a test-first strategy, would these moments of scope creep been prevented? Probably not; however, it would have probably allowed me to be more conscience of the decision and possibly move it to some form of feature list for another iteration.

I only use standard NUnit-based unit tests and haven't fully tried out writing specs associated with BDD. Using something like a full spec like BDD would have been able to control the feature list a bit better but, again, not fully prevent scope creep. Regardless of the method, staying focused on a test-first approach does have a habit of controlling and identifying scope creep. It's easier to finishing a single iteration and enhance/refactor than it is to always go with the flow and allow the scope to continue to grow.

Tuesday, December 22, 2009

Using MEF and Custom Configuration Sections

Up to this point, I've dove into some of the core fundamentals of using the Managed Extensibility Framework.  Starting with this post, we're going to dive into how to apply it under certain circumstances.  Some of the scenarios in the upcoming posts will focus on using MEF with different .Net technologies, applications that use MEF, or tricks in .Net that can assist when working with MEF.  In this post, we'll start with this last category of scenarios by looking at how to utilize a custom configuration section defined in an assembly used as a MEF part and not located in the same directory as the executable.  Using this method, it will allow even greater power to your application and freedom to the parts consumed by such.

Setting the Stage

For this post, we'll look at a simple code base we worked on earlier in the series which imported MEF parts from a separate assembly.  Let's extend the code base by defining our simple custom configuration section from within the same assembly that define our external part.  For simplicity sake, let's call the custom configuration section MEFCustomConfigSection.  Below is the code for our custom configuration section:

   1:  public class MEFCustomConfigSection : ConfigurationSection
   2:  {
   3:      private static MEFCustomConfigSection settings = ConfigurationManager.GetSection("MEFCustomConfigSection") as MEFCustomConfigSection;
   4:   
   5:   
   6:      public static MEFCustomConfigSection Settings
   7:      {
   8:          get { return settings; }
   9:      }
  10:   
  11:      [ConfigurationProperty("message", IsRequired = true)]
  12:      public string Message
  13:      {
  14:          get { return this["message"].ToString(); }
  15:          set { this["message"] = value; }
  16:      }
  17:  }

This configuration section is very simple in that it only defines one property/attribute called Message.  This property will contain a string value in which we'll be displaying on the screen when the application consumes our part.

Consuming Our Section

Now that our configuration section has been defining, let's go ahead and create the code to consume such.  In previous examples, each of our parts had a property called HelpText that is used by the consuming application to display command line help documentation for each part.  What we will do with this new part is using our configuration section's Message property to define what the value of the HelpText property should be.  Thankfully, the code for this is extremely simple as shown below:

   1:  [Export("command", typeof(IHelp))]
   2:  public class CustomCommand : IHelp
   3:  {
   4:      public string CommandName
   5:      {
   6:          get { return "Custom"; }
   7:      }
   8:   
   9:      public string HelpText
  10:      {
  11:          get { return MEFCustomConfigSection.Settings.Message; }
  12:      }
  13:  }

Setting Up the Configuration File

Now that we have the custom configuration section created and code that needs it, we're now ready to update our consuming application's App.config file.

   1:  <configuration>
   2:      <configSections>
   3:          <section name="MEFCustomConfigSection" 
   4:                   type="MEFExample7.Commands.MEFCustomConfigSection, MEFExample7.Commands" />
   5:      </configSections>
   6:   
   7:      <MEFCustomConfigSection message="Hello From a Custom Section" />
   8:   
   9:      <runtime>
  10:          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  11:              <probing privatePath="Plug-ins;" />
  12:          </assemblyBinding>
  13:      </runtime>    
  14:  </configuration>

Setting up the custom configuration section is the same as any other configuration section that would need to be setup.  We first define our section within the <configSections> node and then we're able to insert our section; however, what's that last section?

The <runtime> section in the above snippet is needed to tell .Net to scan the Plug-ins subdirectory for the assembly that contains our configuration section.  There are two ways of doing this.  The example above uses the <probing> node which is great for little examples like this; however, can lead to performance issues since it will scan all assemblies in the paths that are provided.  Another issue with the <probing> node is that it doesn't provide a way for targeting specific, strongly named assemblies nor specific assembly versions.  If you need stronger control of what assemblies gets loaded, you can use the <codeBase> node instead.

For more information on using the <probing> and <codeBase> nodes for loading assemblies this way, feel free to check out the following links:

NOTE: One final item I need to mention about using <probing>, it can only look in subdirectories of the location the executable is in.  So if the assembly is in /bin, your path to probe for assemblies cannot be in a parent directory.

Once the configuration section is setup, and the Plug-ins directory is a child directory of the location of the executable, our new command is now displayed when the application runs.

Summary

In this post, we briefly looked at some things to be aware of when defining a custom configuration section from with in an assembly used as an external MEF part.  In future posts, we'll be looking at other scenarios on using MEF including consuming parts written in F# by a C# application as well as take a look at an open source project that will soon be releasing a new version that uses MEF.

Resources

kick it on DotNetKicks.comShout it

Tuesday, December 1, 2009

Managing Composition Through Lazy Loading Parts

So far in this post series, we've been looking at various aspects of working with MEF in the context of a single level of composition.  One interesting thing about MEF is that its composition is recursive based on the assemblies and types identified in the catalogs within the container.  What this means is that if one of our parts also has imports defined for parts of its own, the composition container will continue loading parts for the initial type as well as all parts loaded until no more parts are found or all imports are fulfilled.  This is a really nice feature since it will ensure everything is ready for you once compose the initial type; however, this eager loading can greatly cause a performance issue if the parts are not constructed properly.  In this post on our ongoing series about MEF, we'll look into the concept of parts of parts and how to apply lazy loading principles towards them.

Putting the Pieces of Pieces Together

To start this example off, we'll add to the code we last used in the fourth post of this series (Playing Nice with Other Assemblies using MEF Catalogs).  In order to enhance the code to illustrate a part of parts, let's add a new field to our IHelp interface that will represent subcommands of our parts.  Since we're going to assume that any of our commands could have multiple subcommands, let's make it of type IEnumerable<IHelp>.  Since it's an enumeration of IHelp, the amount of embedding could be infinite in theory (which sounds like fun but maybe another time).  After we update our IHelp interface and our current commands, let's mark only our ExampleCommand class to have its Subcommands property to be a MEF Import point as shown below.

IHelp.cs

   1:  public interface IHelp
   2:  {
   3:      string CommandName { get; }
   4:      string HelpText { get; }
   5:      IEnumerable<IHelp> Subcommands { get; set; }
   6:  }

ExampleCommand.cs

   1:  [Export("Commands", typeof(IHelp))]
   2:  public class ExampleCommand : IHelp
   3:  {
   4:      private string _helpText = "Lorem ipsum dolor sit amet, c ..." +
   5:                                      "Nulla molestie erat rhon ..." +
   6:                                      "amet dolor. Aliquam rhon ..." +
   7:                                      "vel est. Vestibulum et u ..." +
   8:                                      "id tellus. Fusce lectus  ..."
   9:   
  10:      public string CommandName
  11:      {
  12:          get { return AppName + " Example1"; }
  13:      }
  14:   
  15:      public string HelpText
  16:      {
  17:          get { return _helpText; }
  18:      }
  19:   
  20:      [ImportMany("Subcommands", typeof(IHelp))]
  21:      public IEnumerable<IHelp> Subcommands { get; set; }
  22:   
  23:      [Import("AppName")]
  24:      public string AppName { get; set; }
  25:  }

With this done, let's modify our Program.cs code slightly as well.  In order to ensure the we can infinitely loop through our subcommands, let's change our output information slightly by using recursion as shown below.

   1:  void Run()
   2:  {
   3:      Compose();
   4:   
   5:      OutputHelp(Commands, 0);
   6:      Console.ReadKey();
   7:  }
   8:   
   9:  private void OutputHelp(IEnumerable<IHelp> helpCommands, int padding)
  10:  {
  11:      foreach (var help in helpCommands)
  12:      {
  13:          Console.WriteLine(string.Empty.PadLeft(padding, '-') + FormatCommandOutput(help));
  14:   
  15:          if (help.Subcommands != null && help.Subcommands.Count() > 0)
  16:          {
  17:              OutputHelp(help.Subcommands, ++padding);
  18:          }
  19:      }
  20:  }

In the above code, we're passing our recursive function, OutputHelp, two parameters.  The first parameter represent the collection of IHelp instances to be outputted to the screen while the second is to provide depth of the recursion.  On line 13 of the snippet above we use this depth parameter to append our formatted command name with hyphens equal to the depth.  Lastly, we check to see if the Subcommands collection has values and call our OutputHelp method again passing the collection and incrementing the depth.

Next, let's create a new class called ExampleSubcommand.cs.  This will represent a subcommand for our ExampleCommand.cs class.  Once our ExampleSubcommand is all set, we can run the application to see the following output.

Example6-OutputTest1

In the above image, we can see our Subcommand being displayed after the Example1 command as expected.  In addition, we've applied the hyphens prior to the command name to indicate the depth correctly.  Alternatively, we could have added an export to our ExampleCommand class similar to that of our AppName property to send the "MEFExample6 Example1" down the tree as well.

Working with Lazing Parts

Now that we have our example prepped, it's time to see what we can do to optimize the code slightly through lazy loading.  For those who may not be familiar with the concept, lazy loading ultimately means that you do not load the objects or data until they are needed.  What this translates to is that when we call container.ComposeParts(this) in our Program.cs class, we want only our initial commands to be instantiated but not any subcommands it has in order to ensure only the objects that are currently being used are the ones currently in memory.

in order to accomplish lazy loading of exports in MEF, we need to use the System.Lazy<T> type in place of the contract type of our exports.  This type (built into the MEF assembly for .Net 3.5)  tells MEF to delay the instantiation of the value until it's actually called.  This is exactly what we're looking for to prevent a full line of instances from being created as we compose our parts.  Before we dive into the nuances of Lazy<T>, let's look at a simplified snippet below:

   1:  public class LazyExample
   2:  {
   3:      [Import()]
   4:      public System.Lazy<IHelp> command { get; set; }
   5:  }

In the above code, we created an example class called LazyExample which contains a singular import of type IHelp.  Because we wanted to delay the instantiation of this instance, we changed the type from IHelp to System.Lazy<IHelp> and we are all set from a definition standpoint.  While this looks easy, there are two things to be aware of when working with Lazy<T>.

  1. System.Lazy<T> requires you to grab instances of the underlying type using the Value property.  In the example snippet above, we would need to call command.Value in order to get the instance of IHelp instead of just calling the command property like we've been doing up to this point.
  2. System.Lazy<T> is not a collection type.  System.Lazy<T> does not implement nor inherit any class that implement IEnumerable<T>.  What this means is that just wrapping Lazy<T> around your currently defined properties that are decorated with ImportMany() won't work.  In order to apply lazy loading to collections of parts, you must change the type to IEnumerable<Lazy<IHelp>>, keeping inline with the above example.  This means any looping within the collection must be item.Value now instead of just item.

Applying Lazy Loading to Our Exports

Since we now see how to apply lazy loading to our exports, let's modify our code to implement such.  To do this, we'll need to modify our IHelp interface to change the Subcommands property we added to be of type IEnumerable<Lazy<IHelp>> and propagate such between the various parts.  Next, we need to copy our recursive OutputHelp command to create a new method called OutputSubcommandHelp which will address the output.  Once this is done, our code should look something like this:

IHelp.cs

   1:  public interface IHelp
   2:  {
   3:      string CommandName { get; }
   4:      string HelpText { get; }
   5:      IEnumerable<Lazy<IHelp>> Subcommands { get; set; }
   6:  }

ExampleCommand.cs

   1:  [ImportMany("Subcommands", typeof(IHelp))]
   2:  public IEnumerable<Lazy<IHelp>> Subcommands { get; set; }

Program.cs

   1:  [ImportMany("Commands", typeof(IHelp))]
   2:  public IEnumerable<IHelp> Commands { get; set; }
   3:   
   4:  [Export("AppName")]
   5:  public string AppName { get { return "MEFExample6"; } }
   6:   
   7:  void Run()
   8:  {
   9:      Compose();
  10:   
  11:      OutputHelp(Commands, 0);
  12:      Console.ReadKey();
  13:  }
  14:   
  15:  private void OutputHelp(IEnumerable<IHelp> helpCommands, int padding)
  16:  {
  17:      foreach (var help in helpCommands)
  18:      {
  19:          Console.WriteLine(string.Empty.PadLeft(padding, '-') + FormatCommandOutput(help));
  20:   
  21:          if (help.Subcommands != null && help.Subcommands.Count() > 0)
  22:          {
  23:              OutputSubcommandHelp(help.Subcommands, ++padding);
  24:          }
  25:      }
  26:  }
  27:   
  28:  private void OutputSubcommandHelp(IEnumerable<Lazy<IHelp>> helpCommands, int padding)
  29:  {
  30:      foreach (var help in helpCommands)
  31:      {
  32:          Console.WriteLine(string.Empty.PadLeft(padding, '-') + FormatCommandOutput(help.Value));
  33:   
  34:          if (help.Value.Subcommands != null && help.Value.Subcommands.Count() > 0)
  35:          {
  36:              OutputSubcommandHelp(help.Value.Subcommands, ++padding);
  37:          }
  38:      }
  39:  }

Adding Another Subcommand Layer

The last thing we will do in this example is to further extend the recursion tree by adding a new subcommand onto our current ExampleSubcommand.  We'll call it ExampleSubcommand2 and give the contract a label of "Subcommands2".  We'll decorate our ExampleSubcommand class to apply Import such into its own Subcommand collection and we'll run our application to see the following:

Example6-OutputTest2

Summary:

Hopefully after this post you can see the benefits of lazy loading exports as well as how easy it is to implement such.  Given the pattern that we have outlined above, the true depth can open a number of possibilities without over-utilizing our memory.  In the next section, we're going to mix things up a bit by looking at what it may take to have an export be used to defined and interact with a custom configuration section while the assembly is not in the same directory as the calling assembly.

Resources:


kick it on DotNetKicks.comShout it

Wednesday, November 25, 2009

Looking Around at Circular References in MEF

In the last post of this series, we created a new example code base used to display help text for various "commands".  This was a simple code base that extended previous examples by using external assemblies and different catalogs to identify all of the parts that can be imported and mapped.  This example covers a lot of scenarios when applied beyond the means of console-based text output since each imported "command" could literally be a functional piece of code by itself.  However, what happens when the imports require something from our main application?  When one object has a dependency with another object of another type; only for the dependent have a dependency towards the initial type; this is called a circular dependency.  In this post, we're going to look at the condition of a circular dependency and see how MEF encounters such issues.

A Closer Look at Circular Dependencies in General

To reiterate what was said a moment ago, a circular dependency is where two objects depend on each other for different things in somewhat of a symbiotic relationship.  Let's look at an example.  Let's say we have an application that contains two special types.  One type is used to read configuration information and implements the IConfig interface.  The second type is used to log any errors that may occur in the system and implements the IErrorManager interface. 

Example5 - CircularReference

In this illustration, our configuration manager requires an instance of an error manager in case there was an error reading the configuration information.  In addition, our error manager requires an instance of a configuration manager to know how the system is configured for logging errors.  Since each type has a required dependency on the other, a common pattern is to place the required dependencies into a constructor so that the proper dependencies are provided and the type is instantiated in a valid state.  Below is an example what our constructors may look like.

   1:  class ConfigurationManager : IConfig
   2:  {
   3:      private IErrorManager _errMgr;
   4:   
   5:      public ConfigurationManager (IErrorManager errorManager)
   6:      {
   7:          _errMgr = errorManager;
   8:      }
   9:  }
  10:   
  11:  class ErrorManager: IErrorManager
  12:  {
  13:      private IConfig _configMgr;
  14:   
  15:      public ErrorManager(IConfig configManager)
  16:      {
  17:          _configMgr = configManager;
  18:      }
  19:  }

If we have to pass in a valid instance of IErrorManager to our configuration manager, we would first have to instantiate an instance of IConfig for our error manager.  Since there's not a way based on the above code to instantiate a type without the other, the code has to be changed to allow for each to be created in an invalid state and the dependency to be passed to it via a property like below.

   1:  class ConfigurationManager : IConfig
   2:  {
   3:      public IErrorManager ErrMgr { get; set; }
   4:   
   5:      public ConfigurationManager() { }
   6:  }
   7:   
   8:  class ErrorManager : IErrorManager
   9:  {
  10:      public IConfig ConfigMgr { get; set; }
  11:   
  12:      public ErrorManager() { }
  13:  }

The issue with this pattern is that it requires the developer to now remember to always inject the proper dependencies after the types have been instantiated through their constructors.  Ultimately, it's risky because we're all human and tend to forget from time to time.   IoC containers help here a little bit, but can still confuse people.  An alternative solution which many people prefer is to used a bootstrapped version of one of the two objects that doesn't depend on the other.  This pattern also has issues due to what may not be available in a bootstrapped version.  In our example, a bootstrapped IConfig object may not contain any error management code with in it.

Looking At a Simple MEF Circular Reference

Now that we, hopefully, understand a bit more about what a circular reference is and where it can occur, let's see about recreating our example with MEF.   Let's create a program that has a property for a IErrorManager and IConfigMgr instances.  To build the circular reference, let's inject the dependencies through the constructors of our ErrorManager and ConfigManager classes and mark the constructors as Imports.  Below is our Circular Reference implementation.

Program.cs

   1:  namespace MEFExample5
   2:  {
   3:      class Program
   4:      {
   5:          [Import(typeof(IConfigManager))]
   6:          public IConfigManager ConfigurationManager { get; set; }
   7:   
   8:          [Import(typeof(IErrorManager))]
   9:          public IErrorManager ErrorManager { get; set; }
  10:   
  11:          static void Main(string[] args)
  12:          {
  13:              var prog = new Program();
  14:              prog.Run();
  15:          }
  16:   
  17:          void Run()
  18:          {
  19:              Compose();
  20:              Console.WriteLine(ConfigurationManager.TestText);
  21:              Console.WriteLine(ErrorManager.TestText);
  22:              Console.ReadKey();
  23:          }
  24:   
  25:          void Compose()
  26:          {
  27:              var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
  28:              var container = new CompositionContainer(catalog);
  29:              container.ComposeParts(this);
  30:          }
  31:      }
  32:  }

ConfigMgr.cs

   1:  namespace MEFExample5
   2:  {
   3:      public interface IConfigManager
   4:      {
   5:          string TestText { get; set; }
   6:      }
   7:   
   8:      [Export(typeof(IConfigManager))]
   9:      public class ConfigMgr : IConfigManager
  10:      {
  11:   
  12:          public string TestText { get; set; }
  13:   
  14:          public ConfigMgr()
  15:          {
  16:              TestText = "Config";
  17:          }
  18:   
  19:          [ImportingConstructor]
  20:          public ConfigMgr(IErrorManager errorManager) : this()
  21:          {
  22:              _errorManager = errorManager;
  23:          }
  24:      }
  25:  }

ErrorManager.cs

   1:  namespace MEFExample5
   2:  {
   3:      public interface IErrorManager
   4:      {
   5:          string TestText { get; set; }
   6:      }
   7:   
   8:      [Export(typeof(IErrorManager))]
   9:      public class ErrorManager : IErrorManager
  10:      {
  11:          public string TestText { get; set; }
  12:   
  13:          public ErrorManager ()
  14:          {
  15:              TestText = "Error";
  16:          }
  17:   
  18:          [ImportingConstructor]
  19:          public ErrorManager(IConfigManager configManager) : this()
  20:          {
  21:              _configManager = configManager;
  22:          }
  23:      }
  24:  }

When we try to run this, we get the following error message:

Example5-Error1

As we can see, MEF doesn't completely remove issues inherit from constructor injection-based circular references.  Like we discussed above though, we can move our dependencies into properties instead of a constructor.  What's nice about doing such with MEF though is that we can don't have to truly remember to wire up the dependencies manually.  With the ability to declaratively set our dependent properties as Imports, we won't need any additional code.  Below is the updated code to that addresses the circular reference.

ConfigMgr.cs

   1:  namespace MEFExample5
   2:  {
   3:      public interface IConfigManager
   4:      {
   5:          string TestText { get; set; }
   6:      }
   7:   
   8:      [Export(typeof(IConfigManager))]
   9:      public class ConfigMgr : IConfigManager
  10:      {
  11:          private IErrorManager _errorManager;
  12:   
  13:          public string TestText { get; set; }
  14:   
  15:          [Import(typeof(IErrorManager))]
  16:          public IErrorManager ErrorMngr
  17:          {
  18:              get { return _errorManager; }
  19:              set { _errorManager = value; }
  20:          }
  21:   
  22:          public ConfigMgr()
  23:          {
  24:              TestText = "Config";
  25:          }
  26:   
  27:          public ConfigMgr(IErrorManager errorManager) : this()
  28:          {
  29:              _errorManager = errorManager;
  30:          }
  31:      }
  32:  }

ErrorManager.cs

   1:  namespace MEFExample5
   2:  {
   3:      public interface IErrorManager
   4:      {
   5:          string TestText { get; set; }
   6:      }
   7:   
   8:      [Export(typeof(IErrorManager))]
   9:      public class ErrorManager : IErrorManager
  10:      {
  11:          private IConfigManager _configManager;
  12:   
  13:          public string TestText { get; set; }
  14:   
  15:          [Import(typeof(IConfigManager))]
  16:          public IConfigManager ConfigManager
  17:          {
  18:              get { return _configManager; }
  19:              set { _configManager = value; }
  20:          }
  21:   
  22:          public ErrorManager ()
  23:          {
  24:              TestText = "Error";
  25:          }
  26:   
  27:          public ErrorManager(IConfigManager configManager) : this()
  28:          {
  29:              _configManager = configManager;
  30:          }
  31:      }
  32:  }

Summary:

So in this post we looked at Circular References and and how they are handled through MEF.  In the next post of this series, we'll dive into how we can use lazy loading towards imported parts and where they could be applied at.

Resources:


kick it on DotNetKicks.comShout it