dcsimg

Dependency Injection Using the MEF Framework

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


Introduction

The Managed Extensibility Framework (MEF) has solved the common problems encountered when developing enterprise applications. It's a new library introduced in the .NET Framework 4.0, which is essentially an IOC container. MEF also addresses the problem of simplifying the design of extensible applications and components. In this article, I will explain the importance of MEF and where can MEF be applied during dependency injection and plug-in creation.

Problems MEF Has Solved

MEF solved the runtime extensibility problem. By using MEF, any application can work on a plug-in model that needs to create its own infrastructure from scratch. Plug-ins created by using MEF will often be application-specific and cannot be reused across multiple implementations.

  • MEF provides a standard way for the host application to expose itself and consume external extensions.
  • MEF also offers a set of discovery approaches for the application to locate and load available extensions.
  • MEF allows developers tagging extensions with additional metadata, which aims to facilitate rich querying and filtering.

A Sample Application Using MEF

MEF provides a built-in set of elements that allows developers to "export" and "import" objects across projects. These "export" and "import" tags allow developers not to rely on hard dependencies. This is shown in Figure 1.

New Console Application
Figure 1: New Console Application

To demonstrate MEF "export" and "import" functionalities, I have created a Console Application by clicking New Project from the Start page of Visual Studio. It will open the New Project pop-up, as you saw in Figure 1. I have named the project 'PrjMEF' and OK. This will create a new console application project (see Figure 2).

Added reference
Figure 2: Added reference

To use MEF in the previously created console application, I have added the following reference in the project: System.ComponentModel.Composition.

Next, I have defined a container. In that container, all the exported values will be stored. One simple way to do that is to create a class, as mentioned in the following code snippet.

public static class MefInjection
{
   private static CompositionContainer mycontainer;
   public static CompositionContainer MyContainer
   {
      get
      {
         if (mycontainer == null)
         {
            var catalog =
               new DirectoryCatalog(".", "MyMEFProject.*");

            mycontainer = new CompositionContainer(catalog);

         }

         return mycontainer;
      }
   }
}

The preceding code will grab all the exported values from all the assemblies in the same directory starting with "MyMEFProject". Then, I can annotate the classes as mentioned in the following code snippet. The ImportingConstructor attribute will allow us to import objects while I create the instance.

   [Export]

   public class Logger
   {
   }

   [Export]
   public class MyService
   {
      private Logger log;

      [ImportingConstructor]
      public MyService(Logger log)
      {
         this.log = log;
      }
   }

When I need an instance of MyService Object, I can request it from the container, as in the following code snippet. In the previous MyService class, I have a field with an [Import] attribute. This means MEF will resolve the value for me while it is retrieving the exported value for MyService.

MyService myService = MefInjection.Container.GetExportedValue
   <MyService>();

We can have multiple exports, but the way you need to handle them is different. For example, to have a screen with several tabs that are exported, refer to the following code snippet.

public interface ITab { }

[Export(typeof(ITab))]
public class HomeTab : ITab { }

[Export(typeof(ITab))]
public class GamesTab : ITab { }

[Export(typeof(ITab))]
public class WishlistTab : ITab { }

Finally, the next code snippet shows the entire console application code.

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PrjMEF
{
   class Program
   {
      static void Main(string[] args)
      {
      }
   }

   public static class MefInjection
   {
      private static CompositionContainer mycontainer;
      public static CompositionContainer MyContainer
      {
         get
         {
            if (mycontainer == null)
            {
               var catalog = new DirectoryCatalog(".",
                  "MyProjectNamespace.*");

               mycontainer = new CompositionContainer(catalog);

            }

            return mycontainer;
         }
      }
   }

   public interface ITab { }

   [Export(typeof(ITab))]
   public class HomeTab : ITab { }

   [Export(typeof(ITab))]
   public class GamesTab : ITab { }

   [Export(typeof(ITab))]
   public class WishlistTab : ITab { }

   [Export]
   public class Home
   {
      [ImportMany]
      private List<ITab> tabs;
   }

   [Export]
   public class Logger
   {
   }

   [Export]
   public class MyService
   {
      private Logger log;

      [ImportingConstructor]
      public MyService(Logger log)
      {
         this.log = log;
      }
   }


}

Conclusion

MEF is a powerful framework for creating extensible applications, and should definitely be taken into consideration when designing an application. I hope this article was helpful! That's all for today; happy reading!



About the Author

Tapas Pal

I am working in Microsoft Technology for last 15 years and presently working with Cognizant Technology Solutions, India as Senior Architect. I have completed TOGAF 9.1,Microsoft Certification on .NET 1.1 , .NET 2.0, SQL Server 2005 and Sharepoint. Please visit my Blog - http://tapas-pal.blogspot.com/

Related Articles

Comments

  • There are no comments yet. Be the first to comment!

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date