MEF (Managed Extensibility Framework) is an important library of the. NET Framework 4.0, and the extended support for Visual Studio Code Editor is also built on MEF . The goal of MEF is to simplify the creation of extensible applications whose core class is Composablepart, which is a component with the ability to assemble, each of which is called a composablepart (Chinese can be a composable component, although the following is always used in English, so the more appropriate) components can be combined ( Called import) the functionality of other components (other components provide functionality by declaring export) and it can also expose its functionality to other components by defining export.
Composablepart through the component catalog (Composablepartcatalog) to search for the functionality that is needed, the component directory can be a physical file directory, networked storage, and so on. Each composablepart also has the ability to combine dynamically, which can be re-assembled if necessary. This article will use the bottom-up approach to experience the MEF design ideas.
1. No Nonsense MEF
The core of MEF is the Composable component Composablepart, which is described and created by Composablepartdefintion. Each composable component provides functionality to other components by defining exportdefintion, and by importdefinition referencing the functionality of other components, metadata to describe the information of the component itself. After you create a Composablepart component, you implement the component combination by searching for the required functionality in the component catalog (Composablecatalog).
2. Typical MEF combination process
(1) Creating a component directory (such as Assemblycatalog)
(2) Create a composite container compositioncontainer, component container through component Catalog Search component definition
(3) Create a component
(4) Get the definition of other component functions from the component container, then perform the matching combination
The sample code is as follows:
1. var catalog = new Assemblycatalog (assembly.getexecutingassembly ()); Create an assembly directory to get all the component definitions from an assembly
2. var container = new Compositioncontainer (catalog); Create a composite container
3. var composablepart = new MyComponent ();
4. Container.composeparts (Composablepart); Perform a combination, get exportdefinition from the container, and create instances to group together
5.//Composablepart combination complete for use
The principle is as follows (from Mef.codeplex.com official website):
3 MEF Essential Composition Primitives
A composite primitive is an essential support for providing an extensible, composable component that is at the very bottom of the MEF and is the core class of the entire framework, made up of 6 classes, as shown in the MEF white Paper, the white Paper is a little abstract, but it looks very enjoyable, with the Chinese version of my translation appended to it.
The composition primitive classes are described as follows:
(1) Composablepart: You can combine components, which is the core class of a composite primitive. Exportdefinitions represents the description of the functionality provided by the component, while Importdefinitions is a description of the constraints that reference the functionality of other components. Metadata is a special identifier for the component itself, and when a Composablepart references other component functions through import, the metadata may be a condition that satisfies the constraints of the reference function.
(2) Exportdefinition: Defines the functionality that Composablepart provides to other components, which is described using a ContactName and metadata. ContactName is the contract that uses this function, metadata is used to further describe this function.
(3) Importdefinition: Defines the Composablepart reference to the functionality provided by other components, that is, a exports that references another component. Importdefintion uses an expression to describe the constraint, which is defined in the constraint property, and its type is expression>. This expression is used to make a matching decision for a exportdefintion, which matches the following method:
Here is the code snippet:
1. var allexportdefs = ...//get all exportdefinition from Composablepartcatalog
2. Var constraintdelegate= constraint.compile (); A proxy compiled into a matching function
3. var satisfiedexportdefs = allexportdefs. FindAll (constraintdelegate); Use the proxy of the matching function to filter all the Exportdefs
(4) Composabledefinition: The Composablepart definition is the factory of Composablepart, which defines a class of Composablepart-referenced functions, exposed features, and their own meta-data. The referenced functionality is described in Importdefinitions, and the exposed functionality is described by exportdefinitions. While metadata is a description of the component itself, it is commonly used in MEF to determine whether to combine the functionality provided by another component by matching the metadata of another component when one component references (Import) another component's functionality. This class is the factory of Composablepart and provides the CreatePart method.
(5) Composablepartcatalog: Composable component catalogs, which are used to discover components that may come from physical directories, networked storage, and so on.
4. How to use MEF
On top of that, we describe the core composition primitives of MEF, which sounds simple and easy to understand, but it is not so easy to write a composablepartdefinition directly using a composite primitive, and in the implementation of MEF, these classes are abstract classes. A model used to describe the entire extensible framework. I don't want to talk about how the MEF is going to use a composite primitive, so let's look at the example.
4.1 Definition Composablepartdefinition
MEF simplifies the definition of Composablepart by introducing an attribute-based programming model, as shown in the Messagesender and processor classes are composablepart definitions.
Here is the code snippet:
1. public class Messagesender
2. {
3. [Export ("Messagesender")]
4. public void Send (String message)
5. {
6. Console.WriteLine (message);
7.}
8.}
9. [Export]
public class Processor
11. {
[Import ("Messagesender")]
Public Action Messagesender {get; set;}
public void Send ()
15. {
Messagesender ("processed");
17.}
18.}
4.2. Create Composablepart
Here is the code snippet:
1. var catalog = new Assemblycatalog (assembly.getexecutingassembly ()); Create an assembly directory to get all the component definitions from an assembly
2. var assemblycatalog = new Assemblycatalog (assembly.getexecutingassembly ()); Creating a Component Catalog
3. var container = new Compositioncontainer (assemblycatalog); Creating a composite container
4. var processorpart = new Processor ();
5. Container.composeparts (Processorpart); Execution combination
6. Processorpart.send ();
7. Console.ReadLine ();
4.3, based on the nature of the characteristic programming model
Through the examples of 4.1 and 4.2, we can find that both types of Messagesender and processor are implementations of composablepartdefintion, and in both of these types, we pass export and import (ImportMany) attribute to define the features that are exposed and the functions that are referenced. Compositioncontainer searches all composable component definitions through the component catalog of the assembly where the two classes are located, and then creates the export object with these definitions when the composition is executed, implementing a combination of components according to the constraint contract of the import declaration.
In this programming model, it allows us to: (1) define a composablepartdefinition using the type definition of the traditional OOP, without doubt, this basically does not introduce the complex concept; (2) Use export/import/ ImportMany and other meta-data to declare the composition function, very simple and easy to understand.
Compositioncontainer will build this part-corresponding composablepartdefinition and other composablepartdefinition of the component directory in the background, when performing the combination, Create instance execution combinations with definition.
5. MEF vs MAF vs Unity
When learning MEF, you often ask the question of what the difference is between a plug-in framework like MEF and MAF and an IOC framework like unity. The biggest difference between MEF and MAF (Managed Addin Framework) is that the former focuses on using a very simple way to support scalable support with strong flexibility, which focuses on plug-in platform architectures with physical isolation, security, and multi-versioning support; The difference between MEF and unity is that the former emphasizes the combination and the latter emphasizes dependency injection.
6. MEF Summary
MEF has 3 points to make me very deep, first of all, the design of composite primitives, followed by the feature-based programming model, and finally the implementation of the MEF method.
Composite primitives are the essence of extensible support, and they look very simple, but have the ability to support powerful functionality without sacrificing flexibility. The Boulevard to Jane, however, the degree of Jane is indeed individual, the MEF's Jane really makes people admire pleasantly surprised. This framework is also a frame that I like very much in addition to ObjectBuilder, and it's really nice to see the code.
The work of heaven and man! The creative power of these people is so powerful!
The feature-based programming model, which allows us to define a component with a combination of capabilities using the class's definition + attribute declaration, makes it very, very simple to write components based on MEF! It also makes me feel the charm of context-oriented programming. Later I will also introduce a context-based design of FW that I have done, and the idea of MEF is somewhat similar.
When the MEF is implemented, its top-level namespace is System.ComponentModel.Composition, which divides Attributemodel, diagnostics, Hosting, Primitives, The Reflectionmodel namespace. The MEF's top-level namespace defines the features we use the most, and the bottom namespaces are used to define attribute models, diagnostic support, MEF hosts, composite primitives, and reflection models, and the overall implementation is very clear and concise! Look, I fell in love with this thing at first sight!
7. Another example of an attribute-based programming model
I originally designed a feature-based intelligent body programming framework. First, let me briefly describe what a smart body is. Intelligence is the software agent, using software to simulate human characteristics, including intelligence, initiative, sociality, perception and so on. From an implementation perspective, an agent is a thread-bound, message-queuing object that uses threads to simulate the human brain and use message queues to simulate brain memory. When the agent receives a message, its thread takes over to handle it. According to the above description, you must think that using OOP to develop a smart body is a bit cumbersome. OK, let's see how I use context to implement the agent.
7.1 Using attributes to declare a person with perceived ability and initiative
Here is the code snippet:
1. [Agent]
2. public class Someperson
3. {
4. [Intelligent]
5. Public virtual Openthedoor ()
6. {
7.//Open Door, initiative method
8.}
9. [Sensible (Environment.temperature)]
Public virtual ontemperaturechanged (Sensibilitycontext context)
11. {
12.//When sensing a response to a temperature change, a perceptual statement
13.}
14.}
7.2 Creating a smart body
Here is the code snippet:
1. var agentcontainer = new Agentcontainer ();
2. var agent = Agentcontainer.build (); Build a real smart body in the background
3. Agent. Openthedoor (); Invoking the Openthedoor method, the call will eventually be transformed into a message sent to the real agent by itself, as if someone had left the other person to close the door, and eventually the person receiving the message would perform the action of closing the door.
Agentframework has a similar design approach to MEF (of course, our internal strength and Microsoft are not comparable), by defining the type + claims agent features to define the agent, this method is simple, flexible and extensible!
MEF ——. The subtle design that is worth experiencing in net (go)