
With this article I begin a cycle, the purpose of which is to create the most complete guide to the
Managed Extensibility Framework (MEF) in Russian. The result of the cycle, in my plans, will be the creation of a free e-book about MEF. If you have any thoughts or suggestions on this, let me know in the comments. I hope that together we can create excellent leadership.
This article is based on my reports on MEF at various meetings, including at the DevConf conference.
I'm looking for co-authors, critics, just people who want to help, including with the layout of the document.
')
Chapter 1. Introduction
What is MEF?
Managed Extensibility Framework is the fruit of the work of several people at
Microsoft to develop a tool for solving the problem of application extensibility. The project was originally developed under the open source
MS-PL license. MEF developed as a separate library for
.NET 3.5 and was included in
.NET 4.0 as a full-fledged part of the framework. Inclusion of MEF in the standard .NET libraries is an important step and recognition of the value of this tool.
The purpose of MEF is to provide the developer with the opportunity to add functionality to his application at run time. A very common version of this task is to create plug-ins for a program. Using MEF, you can easily define the extension points of your code, and a third-party developer will just as easily write separate extensions for your application.
The main ideologue and activist of MEF is
Glenn Block (Glenn Block) - the head of the unit in the .NET Framework team at Microsoft. You can find a lot of material on the framework on Glen’s blog at
http://codebetter.com/blogs/glenn.block/ .
The main source of information on the framework and the place where the source code of the project is located is the site
http://mef.codeplex.com/ . Here you will find a developer guide, a description of the MEF architecture, links to useful resources and training videos, forums, and a bugtracker. The latest version of MEF for .NET 3.5 is Preview 9.
MEF is a young tool, but despite this, there are already many products that use it. The most significant product from the list is
Visual Studio 2010 , which uses MEF both internally (designers of UML and the Entity Framework), and to provide extension APIs to third-party developers. Other examples of using MEF are:
Silverlight Analytics Framework ,
Silverlight Media Framework ,
TypeMock Test Lint ,
RavenDB ,
Caliburn ,
Common Service Locator .
It is worth noting that due to the fact that MEF is a free-licensed project, the framework was successfully transferred to
Mono , an alternative open-source implementation of .NET from
Novell .
MEF destination
What tasks is MEF supposed to solve? To date, in the .net environment there was no uniform tool for solving application expansion tasks. Therefore, when such problems arose, each developer solved it in his own way, to the best of his knowledge, skills, and requirements of the problem. It is quite obvious that this situation leads to the creation of code that is architecturally (or fundamentally) incompatible with each other. That is, by moving from one company to another, you can find a completely different approach in solving the same problem. Figure 1 presents the following result: many projects with different options and configuration extensions.
Fig.1. Problem
MEF aims to overcome this problem. The framework included in .NET 4.0 offers a single way to solve architectural problems of extensibility of an application. Achieving the goal of MEF - the spread of a uniform approach - will allow us to simplify the life of developers and make the maintenance of someone else's code or writing extensions to other people's applications much easier and in a familiar (regular) manner (Fig. 2).
Fig.2. Decision
In an ideal perspective, a developer who has studied MEF will be able (without much difficulty and a lengthy study of architecture) to develop components for all sorts of projects on the .NET platform, written by any other companies or individuals. And thus, MEF is able to solve the problem of mutual understanding between developers, offering a common language of communication.
The basics
The key to the success of MEF as a tool lies in its simplicity. MEF is built on just three functional parts: import, export and composition. Using imports, you characterize parts of your application as extensible. A third-party developer, using the export functions, creates a separate component (part, plugin) designed for your application. And, in the course of execution, you use the composition functions to connect parts of the import with parts of the export. Consider these steps in more detail.
Import
In fig. Table 3 shows the definition of some part of the code imported using MEF.
Fig. 3. Imported part
This is where the auto property is defined, the type of which is determined by some kind of interface IPlugin. Using the Import attribute, which is part of the MEF infrastructure, a property is marked as imported. The property itself thus becomes part of the import, and the part type will be the IPlugin interface.
Note the parameter Import: typeof (IPlugin) in this case defines the so-called MEF contract. A contact is a unique identifier that uniquely identifies a part of the import, a part of the export, and thus allows the MEF to connect both parts in the composition process. Simply put, when defining a contract, you provide a certain password, which must be called part of the extension in order to join the point of import. Later in this chapter, contracts will be discussed in more detail.
Export
In fig. 4 gives the definition of a class that implements the exported portion of the extension in MEF.
Fig. 4. Exported part
Here is defined a certain class FirstPlugin, which implements the IPlugin interface (part of the import in the previous topic is defined using the same one). Using the Export attribute from the MEF infrastructure, the class is marked as exported (you can say “plugin”). Note that the Export attribute parameter is a contract declared as typeof (IPlugin). Exactly the same contract was defined in terms of imports in the previous topic.
Defining the same contract when importing and exporting allows MEF to find parts destined to one another.
Composition
After determining the imported and exported parts, it is necessary to produce them (Fig. 5). Composition refers to the process of finding all defined parts of a MEF, instantiating them, and assigning instances of exported parts to parts of an import. In other words, in the process of composition, the plugins marked with the export attribute are connected to parts of yours when they are marked with the import attributes.
Fig. 5. Composition
An instance of the composition container is created here (the container is part of the MEF infrastructure, which will be discussed in more detail later). After that, the container calls the ComposeParts method, whose parameters are an enumeration of the elements in which the MEF should look for parts for the composition. In this case, this is an instance of the current class and new FirstPlugin () is an instantiated plug-in, which we marked in the previous section with the Export attribute.
After calling ComposeParts, the this and FirstPlugin instances will be recorded in the container container, and the imported part of the Plugin (Fig. 3) will receive the value of the FirstPlugin instance (Fig. 4). A little further we will look at the whole process together in the sample code.
An important role in the composition process is played by contracts, which allow us to indicate exactly which parts of exports we expect in a particular part of imports.
Contracts
Contracts in the MEF infrastructure play an important connecting role between parts of imports and exports. Contracts are necessarily explicitly or implicitly defined when parts are imported or exported. In fig. 3, the contract uses the typeof expression (IPlugin), which uniquely identifies the type of the IPlugin interface.
In fact, the MEF infrastructure contains several options for defining a contract during import (Table 1).
Table 1. Options for defining contracts when importing
ImportAttribute (Type) | by specifying the transfer type (as we have considered) |
ImportAttribute (String) | by passing the contract name as a string - in this case, you must ensure that such a string is unique among other contracts |
ImportAttribute (String, Type) | by passing both the contract name as a string and its type — this can be useful when there is a need to create several different contracts for the same type |
ImportAttribute () | if the type of contract was not transferred to the import attributes (Import and others), then it will be determined automatically based on the type to which this attribute is applied. Thus, you can omit the typeof parameter (IPlugin) in the example in fig. 3 |
In cases where the contract name was not transferred, it is generated automatically using the GetContractName method, which returns the full string type definition including its namespace. As already mentioned, if the type of contract is not specified, it is also automatically obtained.
For export attributes, the same rules apply as for import. But when defining export using the attributes of Export and others, it is important to understand the following behavior: if the type and name of the contract are not specified, they will be obtained automatically based on the type of element to which the attribute is applied. In other words, if in the example in fig. 4 omit the typeof parameter (IPlugin), then the MEF infrastructure will automatically determine the contract based on the FirstPlugin type, but not IPlugin, as required by us. This means that if you build an exported part based on basic interfaces or classes, then you need to explicitly specify its type for the contract.
Hello, MEF!
It is time to collect all the knowledge of this chapter and implement it in a concrete example. To demonstrate, let's create a project based on ASP.NET MVC Framework 2 and define the following interface in it:

This interface will determine the type of our imported and exported parts.
Then, in the HomeController controller, we define the import point:

Note that we have defined an import point with a typeof contract (IPlugin). However, in this case, we may well omit this contract definition, entrusting its automatic definition to the MEF infrastructure.
However, the author of this text strongly recommends that you specify contracts whenever you define imported and exported parts. Such a definition will help you to quickly understand the text of the code in the future.
The next step is to define the exported part, you can call its plugin, which will “connect” to the import defined above.

Please note that if in the case of defining imports we could have omitted the contract, then in this case with exports, we cannot omit the contract, because we implement the exported part from the interface that participates in the contract. If we omit the contract definition in this code, we will get an exception at run time from the MEF infrastructure, which cannot find a suitable export part for the import point with the typeof contract (IPlugin).
Our final step is to write the composition code, which we put in the HomeController constructor.

After running the received code, we can observe the expected result (Fig. 6).
Fig. 6. MEF Result
As you can see, after running ComposeParts, the Plugin property accepted the value of an instance of the FirstPlugin class, as intended.
Conclusion
In this chapter, we learned about the MEF framework, its purpose and the problems it addresses. We considered the basic concepts of MEF and some of their features: import, export, composition, contracts. We built the first example on the basis of the information received, which demonstrated the work of MEF in practice.
In the next chapter, we dive into the framework, consider a more complex example with several plugins, and introduce the concept of directories in MEF.