Click here to Skip to main content
15,885,887 members
Articles / Programming Languages / C#
Article

Simple MEF Application for Beginners

Rate me:
Please Sign up or sign in to vote.
3.46/5 (10 votes)
31 Jul 2012CPOL3 min read 66.7K   2.6K   15   10
This article demonstrates the usage of MEF through a simple example.

Sample Image - maximum width is 600 pixels

Introduction

I am not going to cover the details of MEF or describe the functionality of MEF. You can find good material over the net for MEF, so I am not going to post redundant information. MEF is an extensibility framework provided by Microsoft. Many other extensibility frameworks exist but MEF is easy to initiate. Today I am going develop a sample application which demonstrates how to import/export components. Kindly note that this is just a small effort so that beginners can start working with MEF.

Using the code

In this article we are going to cover the following topics:

  1. Develop Component behavior: This will be an interface whose functionality is exported by components and consumed by our host application.
  2. Host application: Application that seeks for a component to be composed.
  3. ExportLib1, ExportLib2: These are components – actual implementation of our component behavior.
  4. Main application: This uses all these.

So let's start with the first part of our application.

  1. Create Contract library which contains the IComponent interface as shown below. Through this interface our component will communicate.
  2. C#
    namespace Contracts
    {
        public interface IComponent
        {
            string Description { get; }
            string ManipulateOperation(params double[] args);
        }
    }
  3. Create library ImportingLib; this contains a class that actually hosts and calls the components. Here we have to add the System.ComponentModel.Composition assembly. Code for the Importer class is shown below.
  4. C#
    using System;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Reflection;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using Contracts;
    
    namespace ImportingLib
    {
        public class Importer
        {
            [ImportMany(typeof(IComponent))]
            private IEnumerable<Lazy<IComponent>> operations;
    
            public void DoImport()
            {
                //An aggregate catalog that combines multiple catalogs
                var catalog = new AggregateCatalog();
    
                //Add all the parts found in all assemblies in
                //the same directory as the executing program
                catalog.Catalogs.Add(
                    new DirectoryCatalog(
                        Path.GetDirectoryName(
                        Assembly.GetExecutingAssembly().Location
                        )
                    )
                );
    
                //Create the CompositionContainer with the parts in the catalog.
                CompositionContainer container = new CompositionContainer(catalog);
    
                //Fill the imports of this object
                container.ComposeParts(this);
            }
    
            public int AvailableNumberOfOperation
            {
                get { return operations != null ? operations.Count() : 0; }
            }
    
            public List<string> CallAllComponents(params double[] args)
            {
                var result = new List<string>();
    
                foreach (Lazy<IComponent> com in operations)
                {
                    Console.WriteLine(com..Description);
                    result.Add(com.Value.ManipulateOperation(args));
                }
    
                return result;
            }
        }
    }

    This host imports components implementing IComponent and lists them in private variable operations. The DoImport method initializes the list. Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) gives a path in which our executing assembly resides. MEF will automatically start searching all assemblies in the directory where the calling program resides. This is done by creating a DirectoryCatalog on that folder and then adding it to the main AggregateCatalog. The property AvailableNumberOfOperation returns the number of found operations and the CallAllComponents method calls all the exporting components and returns the result.

  5. As our host is ready for import functionality, a major task is to develop a component that exports the desired functionality. For demonstration, I developed two class libraries which contain classes that implement the IComponent interface. Their code section is shown as below.
  6. C#
    using System;
    using System.ComponentModel.Composition;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Contracts;
    
    namespace ExportSumLib
    {
        [Export(typeof(IComponent))]
        public class SumOfNumberComponent : IComponent
        {
            public string Description
            {
                get { return "Summation of components"; }
            }
    
            public string ManipulateOperation(params double[] args)
            {
                string result = "";
                double count = 0;
                bool first = true;
    
                foreach (double d in args)
                {
                    if (first)
                    {
                        count = d;
                        first = false;
                    }
                    else
                        count += d;
                    result += d.ToString() + " + ";
                }
    
                return result.Trim('+', ' ') + " = " + count.ToString();
            }
        }
    }

    Here you can see the code of the SumOfNumberComponent class. This class is built in the ExportingLib1.dll file. You’ve added a reference for Contracts.dll and System.ComponentModel.Composition.

    The same way we develop another library called ExportingLib2.dll which contains the SubstractOfNumberComponent class. The code for that class is shown below.

    C#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.Composition;
    using Contracts;
    
    namespace ExportSubstractLib
    {
        [Export(typeof(IComponent))]
        public class SubstractOfNumberComponent : IComponent
        {
            public string Description
            {
                get { return "Subtraction of components"; }
            }
    
            public string ManipulateOperation(params double[] args)
            {
                string result = "";
                double count = 0;
                bool first = true;
    
                foreach (double d in args)
                {
                    if (first)
                    {
                        count = d;
                        first = false;
                    }
                    else
                        count -= d;
                    result += d.ToString() + " - ";
                }
    
                return result.Trim('-', ' ') + " = " + count.ToString();
            }
        }
    }

    Now let’s move to the final step of this exercise.

    Create an application that uses all these stuff.

  7. Develop a console application called MEFApplication. Add a reference to ImportingLib.dll. Now write down the code section shown below.
  8. C#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace MEFApplication
    {
        class Program
        {
            static void Main(string[] args)
            {
                var t = new ImportingLib.Importer();
                t.DoImport();
                Console.WriteLine("{0} component(s) are imported successfully.", t.AvailableNumberOfOperation);
                var result = t.CallAllComponents(125, 5, 10, 27, 45, 19, 10);
                foreach (string s in result)
                {
                    Console.WriteLine(s);
                }
                Console.Read();
            }
        }
    }

Before executing the application do this: go to the Project Properties->Build option and set the building path of each application to the bin\Debug folder of the MEFApplication project. Now build the whole project and see the magic.

You can when you execute the MEFApplication project it will show a two component(s) imported successfully message and rest messages. If you remove any of the libraries from ExportingLib1.dll or ExportingLib2.dll, the message will change to 1 component(s) are imported successfully.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Automation Anywhere Inc.
India India
I am Himanshu Manjarawala, Garduate in Computer Science and MCA From Veer Narmad South Gujarat University, Surat Gijarat India. Currently working as Sr. Software Developer in Automation Anywhere Softwares Pvt. Ltd. Vadodara, Gujarat

Comments and Discussions

 
QuestionImport the Complex datatypes like class object or structure Pin
CiaoWorld16-Oct-14 3:30
CiaoWorld16-Oct-14 3:30 
QuestionIs this guy a copy cat? Pin
kvcrajan20-May-14 7:19
kvcrajan20-May-14 7:19 
AnswerRe: Is this guy a copy cat? Pin
Himanshu Manjarawala20-May-14 18:24
Himanshu Manjarawala20-May-14 18:24 
AnswerRe: Is this guy a copy cat? Pin
sobo1237-Feb-15 2:37
sobo1237-Feb-15 2:37 
SuggestionNot clear enough. Check out this example-> Pin
ybonda30-Nov-13 18:30
ybonda30-Nov-13 18:30 
Not very clear...
This what I looked for:
MEF Simple Application in C#[^]
AnswerRe: Not clear enough. Check out this example-> Pin
Himanshu Manjarawala24-Dec-13 2:03
Himanshu Manjarawala24-Dec-13 2:03 
GeneralMy vote of 1 Pin
Nero theZero30-Sep-12 18:56
Nero theZero30-Sep-12 18:56 
GeneralMy vote of 2 Pin
dave.dolan1-Aug-12 2:50
dave.dolan1-Aug-12 2:50 
GeneralWhat populates the "operations" field? Pin
dave.dolan1-Aug-12 2:45
dave.dolan1-Aug-12 2:45 
GeneralMy vote of 4 Pin
cjb11031-Jul-12 21:06
cjb11031-Jul-12 21:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.