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

Introduction to MEF Programming – Importing Multiple Objects

Rate me:
Please Sign up or sign in to vote.
3.00/5 (2 votes)
5 Nov 2010CPOL2 min read 17.9K   4   1
Introduction to MEF programming - importing multiple objects

Importing Multiple Objects

In the previous blog, we discussed the basic MEF attributes. Let us get into advance topics in MEF step by step.

In the previous example, we wrote the code for the main exe, contract library and MEF Part1. Imagine we have another class derived from IGreeting and implements the SayHelloWorld() function. The class diagram and sequence diagram is shown below.

image

Fig: Class diagram of the participating classes.

image

Fig: Sequence Diagram for the above classes

In the previous blog, i posted the code of all the participating classes. Let us add the new UserGreetingClass to the solution.

Coding the MEFPart2 Library

  1. Add a New Project –> Visual C# –> Class Library.Enter Name as MEFPart2. Click OK. Add the following code.
  2. Add a reference to the System.ComponentModel.Composition assembly.
  3. Add a reference to the ContractsLibrary.DLL assembly.
  4. Add the following using statement:
    • using System.ComponentModel.Composition; This allows us to specify the attributes for using MEF.
    • using ContractsLibrary;
  5. Add the following code:
    C#
    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel.Composition; 
    using ContractsLibrary; 
      
    namespace MefLabPart2 
    { 
        [Export(typeof(IGreeting))] 
        public class UserGreeting : IGreeting 
        { 
            public string SayHelloWorld() 
            { 
                return "Hello " + Environment.UserDomainName; 
            } 
        } 
    }

Compile the solution and copy the MEFPart2.DLL to the MainExe\bin\Debug folder, where the MainExe.exe is located. Try running the application. The following error message comes up in the console.

The composition remains unchanged. The changes were rejected because of the following error(s): 
The composition produced a single composition error. The root cause is provided below. 
Review the CompositionException.Errors property for more detailed information.

1) More than one export was found that matches the constraint 
   ‘((exportDefinition.ContractName == "ContractsLibrary.IGreeting") 
   AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") 
   AndAlso "ContractsLibrary.IGreeting".Equals
   (exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))’.

Resulting in: Cannot set import ‘meflab1.Program.Greetings 
(ContractName="ContractsLibrary.IGreeting")’ on part ‘meflab1.Program’. 
Element: meflab1.Program.Greetings (ContractName="ContractsLibrary.IGreeting") –> meflab1.Program

Press any key to continue . . .

The issue here is that the catalog contains two exports and the import is importing only one export. So when the container tries to match the imports and exports, it fails with the above error.

image

Debug information of the catalog.

The Import attribute will only be successfully composed when it matches one and only one export. Other cases will produce a composition error. An ordinary ImportAttribute attribute is filled by one and only one ExportAttribute. If more than one is available, the composition engine produces an error. To import more than one export that matches the same contract, use the ImportMany attribute. Imports marked with this attribute are always optional. For example, composition will not fail if no matching exports are present. The following class imports any number of exports of type IGreeting.

C#
class Program 
{ 
    [ImportMany] 
    public IEnumerable<igreeting> Greetings { get; set; }</igreeting>

Following is the code of the MainExe project.

C#
using System;
using System.IO;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
//using System.ComponentModel.Composition.Primitives; 
using ContractsLibrary;
using System.Collections.Generic;

namespace meflab1
{
    class Program
    {
      [ImportMany]
      public IEnumerable<IGreeting> Greetings { get; set; }

        static void Main(string[] args)
        {
            Program program = new Program();
            program.Run();
        }

        public Program()
        {
            try
            {
                AggregateCatalog aggregatecatalogue = new AggregateCatalog();
                aggregatecatalogue.Catalogs.Add(new DirectoryCatalog(
                    AppDomain.CurrentDomain.BaseDirectory));
                CompositionContainer container = new CompositionContainer(aggregatecatalogue);
                CompositionBatch batch = new CompositionBatch();
                batch.AddPart(this);
                container.Compose(batch);
            }
            catch (FileNotFoundException fnfex)
            {
                Console.WriteLine(fnfex.Message);
            }
            catch (CompositionException cex)
            {
                Console.WriteLine(cex.Message);
            }
        }

        void Run()
        {
            foreach (var mgreeting in Greetings)
            {
                if (mgreeting != null)
                {
                    Console.WriteLine(mgreeting.SayHelloWorld());
                    Console.ReadKey();
                }
            }
        }
    }
}

The source code is available at:

Have fun !!!

License

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


Written By
CEO Astrani Technology Solutions
United States United States
Kishore Babu Gaddam is a Senior Technology Consultant, Technology Evangelist turned Technology Entrepreneur and a regular speaker at national conferences, regional code camps and local user groups with over 14 years of experience in software product development. His experience includes building & managing award-winning software development teams, managing customer relationships, marketing and launching new software products & services. Kishore launched his technology career almost 15 years ago with a Robotics software development startup and has served in multiple roles since including developer, innovation leader, consultant, technology executive and business owner.

A technology specialist in C++, C#, XAML and Azure, he successfully published two applications to Windows store http://bit.ly/WinStoreApp and http://bit.ly/FlagsApp.

Kishore is the author of the popular Microsoft Technologies blog at http://www.kishore1021.wordpress.com/ and his work on Portable Class Library project in Visual Studio 2012– .NET 4.5 was featured on Channel 9 at http://bit.ly/msdnchannel9. Kishore enjoys helping people understand technical concepts that may initially seem complex and perform lot of Research & Development on emerging technologies to help solve some of the toughest customer issues. Kishore spends a lot of time teaching and mentoring developers to learn new technologies and to be better developers. He is a speaker at various code camps around Washington DC area, mainly at Microsoft Technology Center for NOVA code camp (http://bit.ly/novacc12), CMAP Code Camp Fall 2012 (http://bit.ly/novacc12), etc. The majority of his software development experience has centered on Microsoft technologies including MFC, COM, COM+, WCF, WPF, winRT, HTML5, RestAPI and SQL Server. You can follow Kishore on Twitter at www.twitter.com/kishore1021. He can be reached on email at researcherkishore@outlook.com

Comments and Discussions

 
GeneralMy vote of 1 Pin
RadiumBall25-Apr-14 20:25
RadiumBall25-Apr-14 20:25 

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.