.NET 4.0 MEF FAQ (Socket, Plug, and extension)
This FAQ deep dives into .Net 4.0 MEF fundamentals (Import and Export) and also explains when to use MEF over DI / IOC. This article also explains step by step how to use MEF in various technologies like Silverlight, WPF, and ASP.NET.
Please feel free to download by free .NET Ebook which has 400 questions and answers in WCF, WPF, WWF, Silverlight, and a lot more from
here. View our 300 videos Design Patter, UML, Function Points, Enterprises Application Block, WCF, WPF, WWF, LINQ, SQL Server, Silverlight, .NET Project, SDLC, OOP's, .NET Best Practices, ASP.NET 4.0 From
here
MEF is a framework by which you can make your application extensible. For example, you have an accounting application and you would like to provide a hook (socket) where external vendors can connect (plug) and add invoicing capabilities to the accounting application.
For instance, you have an application in which you would want different vendors to connect with their features and extend your application.
So the vendors just put the components in the application, the application discovers them, and does the connection and extension.
Implementing MEF is a three-step process:-
- Import (Create the socket) - Use the "Import" attribute to define a hook or socket in your application.
- Export (Attach the Plug) - Use the "Export" attribute to create the plug which can attach to the plug or hook.
- Compose (Extend it) - Use the composition container and compose it.
We will create a simple class which will have a hook to import string message. In other words, any class that has the functionality of string message implementation can attach itself to the hook and extend that class.
Step 1:- Create the socket (Import)
The first step is to create a place holder/hook/socket where other components can plugin.
Import the below namespaces needed by MEF.
- using System.ComponentModel.Composition;
- using System.ComponentModel.Composition.Hosting;
- using System.Reflection;
To define a hook we have created an empty property called as "ImportMessage" and we have attributed the same with "Import" attribute.
- class Program {
- [Import()]
- public string ImportMessage {
- set;
- get;
- }
- }
The above "import" attribute says that anyone who has a string functionality implementation type can connect to me and attach the functionality.
Step 2:- Create and attach the plug (Export)
In order to create the plug or extension we need to use the "Export" attribute as shown below. This attribute in the current scenario does nothing but displays a simple string.
- class clsMySimpleMessage {
- [Export()]
- string ExportMessage {
- set {}
- get {
- return "Message inserted via MEF";
- }
- }
- }
Step 3: Connect and Extend it (Compose it)
Ok so we have created the socket, the plug and it's time to connect these both. Below goes the code for the same.
- private void Compose() {
-
- AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
- CompositionContainer compositionContainer = new CompositionContainer(catalog);
- compositionContainer.ComposeParts(this);
- Console.WriteLine(ImportMessage);
- Console.ReadLine();
- }
In other words export, import and compose, Below figure summarizes the same.
"Export" is like things you give off and "import" is like things which you take in.
The types of import and export should match or else while composing you will get an error as shown below. Can incompatible socket and plug connect?.
In the real world your hooks would be some real-world contract types like a customer, supplier, etc rather than simple .NET data types like string, int, Boolean, etc. In order to create a real word kind of hook in MEF, we need to first create a contract using interfaces as shown below.
- interface ImyInterface {
- string getString();
- }
We need to ensure that the hooks defined in both import and export attributes are of the same interface type as shown below. The binding logic using the composition container does not change; it's the same as described in the previous section.
- [Export(typeof(ImyInterface))]
- class clsMyImplementation: ImyInterface
- {
- public string getString()
- {
- return "This is my string";
- }
- }
-
- class Program
- {
- [Import()]
- public ImyInterface myInterface
- {
- set;
- get;
- }
- }
In case you are new to DI/IOC read from
here
Both of them overlap each other to a very great extent but the GOALS are different. DI and IOC is meant for decoupling while MEF is for extensibility. The below requirement will throw more light on how to decide which solution to go for:-
Requirement |
Solution |
The application should be a tiered application with each tier decoupled from the other for better reusability and maintainability. |
DI IOC |
The application should provide a facility for exporting data into different formats. External vendors should be able to plug in their own export mechanism into the application. |
MEF |
Below table summarizes the same in a detailed manner.
|
DI / IOC |
MEF |
Decoupling |
Yes |
|
Extensibility |
|
Yes |
Integrate Known things |
Yes |
|
Integrate Unknown thing |
|
Yes |
Automatic discovery |
|
Yes |
Registration |
Yes |
|
Discovery |
|
Yes |
Compile-time |
Yes |
|
Run time |
|
Yes |
If you have still questions post it to Glenn Block over here
http://codebetter.com/blogs/glenn.block/archive/2009/08/16/should-i-use-mef-for-my-general-ioc-needs.aspx
Let say you have an application and the following is your requirement.
Requirement |
Solution |
The application should be 3 tier architecture with UI, BO, and DAL layers decoupled from each other. |
DI IOC |
The data access layer needs to be open and extensible. The application will provide the ability to vendors to plug their own data connection mechanism so that the application can connect to their proprietary databases. |
MEF |
The way to approach the first requirement is by using your favorite IOC container and the second requirement is where MEF fits. The below diagram shows how they fit into the whole game.
The end GOAL is more important when making a choice between them.
Below is a nice article by Mr. Nicholas Blumhardt which shows how MEF and IOC fit in.
http://blogs.msdn.com/b/nblumhardt/archive/2009/03/16/hosting-mef-extensions-in-an-ioc-container.aspx
The main important steps do not change.
Step 1:- Create the socket (Import)
Define the Silverlight items you want to import. In the below code snippet we have defined a collection of user control type.
- public partial class MainPage: UserControl {
- [ImportMany]
- public ObservableCollection < UserControl > ImportedItems { get;
- set; }
- }
Step 2:- Create and attach the plug (Export)
Use "Export" to define the plug. For the current scenario, we have defined two Silverlight user control with export attributes exposing "UserControl" as the type.
- [Export(typeof(UserControl))]
- public partial class SilverlightControl1: UserControl
- {
- public SilverlightControl1()
- {
- InitializeComponent();
- }
- }
- [Export(typeof(UserControl))]
- public partial class SilverlightControl2: UserControl
- {
- public SilverlightControl2()
- {
- InitializeComponent();
- }
- }
Step 3: Connect and Extend it (Compose it)
Use the "SatisfyImport" to compose the exports and imports.
- CompositionInitializer.SatisfyImports(this);
If you run the same you should see the composed user controls in the main Silverlight UI container as shown below.
The whole Silverlight picture looks something as shown below.
Phrrr..phusss….tired will update soon.
Phrrr..phusss….tired will update soon.
You can get the source code attached with this article from the top of this article.