Click here to Skip to main content
15,867,330 members
Articles / Programming Languages / C#

Advanced MEF Programming

Rate me:
Please Sign up or sign in to vote.
3.80/5 (5 votes)
6 Feb 2011CPOL4 min read 33.6K   12   7
Advanced MEF Programming

Types of Imports

.NET 4.0 introduced many new programming concepts and MEF supports some of them. MEF supports several import types, including dynamic, lazy, prerequisite, and optional.

The attached source code contains some of the advanced MEF programming concepts that I did not discuss in this blog. You can debug the source code step by step and explore the concepts.

Dynamic Imports

.NET 4.0 introduces a new type, dynamic. The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object. At compile time, an element that is typed as dynamic is assumed to support any operation. Therefore, you do not have to be concerned about whether the object gets its value from a COM API, from a dynamic language such as IronPython, from the HTML Document Object Model (DOM), from reflection, or from somewhere else in the program. However, if the code is not valid, errors are caught at run time.

In some cases, the importing class may want to match exports of any type that have a particular contract name. In this scenario, the class can declare a dynamic import. The following import matches any export with contract name "DemoOfDynamicImport".

C#
1  [Import("DemoOfDynamicImport")]
2  public dynamic somedynamicclassobject;

When the contract type is inferred from the dynamic keyword, it will match any contract type. In this case, an import should always specify a contract name to match on. (If no contract name is specified, the import will be considered to match no exports.) Both of the following exports would match the previous import. The importing class must be prepared to deal with an object of arbitrary type.

C#
1  [Export("DemoOfDynamicImport", typeof(IGreeting))]
2  public class DemoOfDynamicImportClass
3  {
4      public string SayHelloWorld()
5      {
6          return "Hello from DemoOfDynamicImport Class";
7      }
8  }
Lazy Imports

In some cases, the importing class may require an indirect reference to the imported object, so that the object is not instantiated immediately. In this scenario, the class can declare a lazy import by using a contract type of Lazy<T>. The following importing property declares a lazy import. To explain multiple concepts, I created different objects using different techniques. Please use any one at your convenience.

C#
1  [Import("IMyLazyClass",AllowDefault = true)]
2  public Lazy<MyLazyClass> objlazyclass;
3
4  [ImportMany]
5  public Lazy<IGreeting>[] Greetings1 { get; set; }
6
7  [ImportMany]
8  public IEnumerable<Lazy<IGreeting>> Greetings2 { get; set; }

From the point of view of the composition engine, a contract type of Lazy<T> is considered identical to contract type of T. Therefore, the previous import would match the following export. The following Export matches the Import in line1 of the above code.

C#
1  [Export("IMyLazyClass")]
2  class MyLazyClass
3  {
4      public string SayHelloWorld()
5      {
6          return "Hello from MyLazyClass";
7      }
8  }

The following Export code matches the Import of line4 or line7 of the above Import code. The contract name and contract type can be specified in the Import attribute for a lazy import:

C#
 1  [Export(typeof(IGreeting))]
 2  public class SimpleGreetingClass : IGreeting
 3  {
 4      public string SayHelloWorld()
 5      {
 6          return "Hello World !!!";
 7      }
 8
 9      //Explicitly specifying a generic type.
10      [Export(typeof(Func<int, string>))]
11      public string DoSomething(int TheParam)
12      {
13          return "From Func: You Entered " + TheParam.ToString();
14      }
15  }

Optional Imports

The Import attribute specifies a requirement for the part to function. If an import cannot be fulfilled, the composition of that part will fail and the part will not be available. You can specify that an import is optional by using the AllowDefault property. In this case, the composition will succeed even if the import does not match any available exports, and the importing property will be set to the default for its property type (null for object properties, false for Booleans, or zero for numeric properties.) The following class uses an optional import.

C#
1  [Import("IMyLazyClass", AllowDefault = true)]
2  public Lazy<MyLazyClass> objlazyclass;

Metadata

Exports can provide additional information about themselves known as metadata. Metadata can be used to convey properties of the exported object to the importing part. The importing part can use this data to decide which exports to use, or to gather information about an export without having to construct it. For this reason, an import must be lazy to use metadata. To use metadata, you typically declare an interface known as a metadata view, which declares what metadata will be available. The metadata view interface must have only properties, and those properties must have get accessors. To allow the accessing of metadata, MEF leverages a new API of the .NET Framework 4, System.Lazy<T>. It allows delaying the instantiation of an instance until the value property of the Lazy is accessed. MEF further extends Lazy<T> with Lazy<T,TMetadata> to allow accessing export metadata without instantiating the underlying export. TMetadata is a metadata view type. A metadata view is an interface that defines read-only properties that correspond to keys in the exported metadata. When the metadata property is accessed, MEF will dynamically implement TMetadata and will set the values based on the provided metadata from the export.

The following class is an example metadata. See line25.

C#
 1  using System;
 2  using System.ComponentModel.Composition;
 3  using ContractsLibrary;
 4
 5  namespace MEFPart1
 6  {
 7      [Export(typeof(IGreeting))]
 8      public class SimpleGreetingClass : IGreeting
 9      {
10          public string SayHelloWorld()
11          {
12              return "Hello World !!!";
13          }
14
15          //Explicitly specifying a generic type.
16          [Export(typeof(Func<int, string>))]
17          public string DoSomething(int TheParam)
18          {
19              return "From Func: You Entered " + TheParam.ToString();
20          }
21      }
22
23
24      [Export(typeof(IGreeting))]
25      [ExportMetadata("Name", "Kishore")]
26      public class SimpleMetaDataClass : IGreeting
27      {
28          public string SayHelloWorld()
29          {
30              return "Hello World from SimpleMetaDataClass.
       Checking the metadata name at runtime !!!";
31          }
32      }
33  }

The following class is an example metadata. See line11.

C#
 1  using System;
 2  using System.Collections.Generic;
 3  using System.Linq;
 4  using System.Text;
 5  using System.ComponentModel.Composition;
 6  using ContractsLibrary;
 7
 8  namespace MEFPart2
 9  {
10      [Export(typeof(IGreeting))]
11      [ExportMetadata("Name", "Babu")]
12      public class ExtendedGreeting : IGreeting
13      {
14          public string SayHelloWorld()
15          {
16              return "Hello " + Environment.UserDomainName + "\\" +
                       Environment.UserName;
17          }
18      }
19
20      //[PartNotDiscoverable]
21      // A part decorated with PartNotDiscoverabl attribute
        // will not be included in any catalogs.
22      //So in the main exe, you will get runtime composition error
23      [Export("DemoOfDynamicImport", typeof(IGreeting))]
24      public class DemoOfDynamicImportClass
25      {
26          public string SayHelloWorld()
27          {
28              return "Hello from DemoOfDynamicImport Class";
29          }
30      }
31  }

An import with metadata is declared as a lazy import, with the metadata interface as the second type parameter to Lazy<T,T>. The following class imports the previous part with metadata.

C#
1  [ImportMany]
2  public IEnumerable<Lazy<IGreeting, IGreetingMetadata>> greetingmetadata

Once a collection of lazy exports with metadata has been imported, you can use LINQ (commented) to filter against the set as shown in the following code snippet:

C#
 1  foreach (Lazy<IGreeting, IGreetingMetadata>
       greetingmeta in greetingmetadataobjects)
 2  {
 3      if (greetingmeta.Metadata.Name == "Kishore")
 4      {
 5          Console.WriteLine(greetingmeta.Value.SayHelloWorld());
 6          //or we can create an object depending on the metadata value at runtime
 7          IGreeting objgreeting = greetingmeta.Value;
 8          Console.WriteLine(objgreeting.SayHelloWorld());
 9      }
10  }
11
12  ////The below commented code also performs the same task as the following code.
13  ////Following is the code incase, you want to create an object of a class using LINQ
14  //IEnumerable<IGreeting> objgreeting = greetingmetadataobjects.Where
       (v => v.Metadata.Name.Equals("Kishore")).Select(v => v.Value);
15  //foreach (var greeting in objgreeting)
16  //{
17  //    if (greeting != null)
18  //    {
19  //        Console.WriteLine(greeting.SayHelloWorld());
20  //    }
21  //}
Source Code is available at

Microsoft: http://cid-38ecce05b21b8b44.office.live.com/self.aspx/MY%20Projects/All%20MEF%20Concepts.zip

"Do not follow where the path may lead. Go instead where there is no path and leave a trail."


Filed under: Advance MEF Concepts, CodeProject, MEF

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 3 Pin
Vitaliy Markitanov30-Oct-13 4:21
Vitaliy Markitanov30-Oct-13 4:21 
GeneralRe: My vote of 3 Pin
kishore Gaddam30-Oct-13 4:32
kishore Gaddam30-Oct-13 4:32 
This article is part of a series of articles from my blog. you need to follow all parts to understand what was written earlier. please see my blog for all the articles.
Follow the popular Microsoft Technologies blog at http://www.kishore1021.wordpress.com/

See Windows store http://bit.ly/WinStoreApp and http://bit.ly/FlagsApp.

GeneralMy vote of 3 Pin
Ralph Shillington18-Sep-13 1:59
Ralph Shillington18-Sep-13 1:59 
GeneralGood post Pin
Libish Varghese Jacob8-Jul-12 21:49
Libish Varghese Jacob8-Jul-12 21:49 
QuestionNot Advanced MEF Pin
IAbstract10-Jul-11 5:46
IAbstract10-Jul-11 5:46 
AnswerRe: Not Advanced MEF Pin
kishore Gaddam11-Jul-11 8:17
kishore Gaddam11-Jul-11 8:17 
GeneralRe: Not Advanced MEF Pin
pbalaga25-Aug-11 4:49
pbalaga25-Aug-11 4:49 

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.