MEF Book

    imageWith this article, I begin a cycle whose purpose is to create the most comprehensive manual on 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 about this, let me know in the comments. I hope that together we can create an excellent guide.

    This article is based on my reports on MEF at various meetings, including at the DevConf conference.

    I am looking for co-authors, critics, just people who want to help, including with the layout of the document.

    Chapter 1. Introduction


    What is MEF?


    The Managed Extensibility Framework is the result of several people working at Microsoft to develop a tool to solve application extensibility problems. The project was originally developed under the open source MS-PL license. MEF developed as a standalone library for .NET 3.5 and was included in .NET 4.0 as a full-fledged part of the framework. The 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 runtime. An extremely common variant of such a task is the creation of plugins for the program. Using MEF, you can easily determine the extension points of your code, and a third-party developer will just as easily write separate extensions for your application.

    The main ideologist and activist MEF is Glen Power (Glenn Block) - unit manager 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 project source codes are located is the sitehttp://mef.codeplex.com/ . Here you will find the developer’s guide, a description of the MEF architecture, links to useful resources and a training video, forums, bug tracker. 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 (UML and Entity Framework designers) and to provide extension APIs to third-party developers. Other examples of using MEF: 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 project with a free license, the framework has been successfully ported to Mono , an alternative open source .NET implementation from Novell .

    Appointment MEF


    What tasks is MEF designed to solve? To date, in the .net environment there was no uniform tool for solving the problems of expanding applications. Therefore, when such a problem arose, each developer solved it in his own way, to the extent of his knowledge, skills, and requirements of the task. It is clear that this situation leads to the creation of code that is architecturally (or fundamentally) incompatible with each other. That is, moving from one company to another you can find a completely different approach to solving the same problem. Figure 1 shows this result: many projects with different options and extension configurations.

    image
    Fig. 1. Problem

    MEF aims to overcome this problem. The framework included in .NET 4.0 offers a single way to solve the architectural problems of application extensibility. Achieving the goal of MEF - spreading a uniform approach - will allow us to simplify our life for developers and make maintaining someone else’s code or writing extensions to someone’s applications much easier and in a familiar (regular) manner (Fig. 2). Fig. 2. Solution In an ideal perspective, a developer who has studied MEF will be able (without much complexity and a long study of architecture) to develop components for various 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.

    image




    The basics


    The key to the success of MEF as a tool lies in its simplicity. MEF is built on only three functional parts: import, export and composition. Using imports, you characterize parts of your application as being extensible. A third-party developer, using the export functions, creates a separate component (part, plug-in) designed for your application. And, at run time, you use composition functions to combine parts of the import with parts of the export. Consider these steps in more detail.

    Import


    In fig. Figure 3 shows the definition of some part of the code imported using MEF.

    image
    Fig. 3. Imported part

    An automatic property is defined here, the type of which is determined by a certain IPlugin interface. Using the Import attribute, which is part of the MEF infrastructure, marks the property as being imported. Thus, the property itself becomes a part of the import, and the type of part will be the IPlugin interface.

    Pay attention to the attribute 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 an import, a part of export, and thus allows MEF to connect both parts in the composition process. Simply put, when defining a contract, you are reporting a password that should be called part of the extension in order to join the import point. Later in this chapter, contracts will be discussed in more detail.

    Export


    In fig. 4 defines a certain class that implements the exported part of the extension in MEF.

    image
    Fig. 4. The exported part.

    Here, a certain FirstPlugin class is defined, which implements the IPlugin interface (the import part in the previous topic was defined using it). Using the Export attribute from the MEF infrastructure, the class is marked as the exported part (you can say “plugin”). Please note that the parameter of the Export attribute 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 for import and export allows MEF to find parts intended for each other.

    Composition


    After determining the imported and exported parts, it is necessary to compose them (Fig. 5). A composition refers to the process of searching for all defined parts of an MEF, instantiating them, and assigning instances of exported parts to import parts. In other words, during the composition process, plugins marked with the export attribute are connected to parts of your when marked with import attributes.

    image
    Fig. 5. Composition

    An instance of the composition container is created here (the container is part of the MEF infrastructure, and will be discussed in more detail below). After that, the ComposeParts method is called on the container, the parameters of which 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 the instantiated plugin that we marked in the previous part with the Export attribute.

    After calling ComposeParts, instances of this and FirstPlugin will be written in the container container, and the imported part of Plugin (Fig. 3) will receive the value of the FirstPlugin instance (Fig. 4). A little further we will consider the whole process together in the sample code.

    An important role in the composition process is played by contracts that allow us to indicate exactly which parts of the export we expect in a particular part of the import.

    Contracts


    Contracts in the MEF infrastructure play an important connecting role between parts of import and export. Contracts are necessarily explicitly or implicitly defined when importing or exporting parts. In fig. 3, typeof (IPlugin) is used as a contract, which uniquely identifies the type of IPlugin interface.
    In fact, the MEF infrastructure contains several options for defining a contract upon import (Table 1).

    Table 1. Options for determining contracts for import
    ImportAttribute (Type)by specifying a type transfer (as we have considered)
    ImportAttribute (String)by passing the name of the contract as a string - in this case, you must definitely guarantee the uniqueness of such a string among other contracts
    ImportAttribute (String, Type)by passing both the name of the contract 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), 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 when the name of the contract has not been transmitted, it is generated automatically using the GetContractName method, which returns the full string definition of the type including its namespace. As already mentioned, if the type of contract is not specified, then it is also obtained automatically.

    For export attributes, the same rules apply as for import. But when defining an export using Export attributes 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 (IPlugin) parameter, the MEF infrastructure will determine the contract automatically based on the type of FirstPlugin, but not IPlugin, as we require. This means that if you are building an exported part based on basic interfaces or classes, then you need to explicitly specify its type for the contract.

    Hello, MEF!


    The time has come to collect all the knowledge in this chapter and implement it in a specific example. To demonstrate, we will 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 the import point with the typeof (IPlugin) contract. However, in this case, we may well omit this definition of the contract, entrusting its automatic determination to the MEF infrastructure.

    image





    image


    However, the author of this text strongly recommends specifying contracts whenever you define imported and exported parts. Such a definition will help you quickly understand the code in the future.
    The next step is to define the exported part, you can call it a plug-in that will “connect” to the import defined above. Please note that if we could omit the contract in the case of import determination, then in this case we cannot omit the contract, as we are implementing the exported part from the interface that participates in the contract. If we omit the definition of the contract in this code, we will get an exception at runtime from the MEF infrastructure, which cannot find a suitable export part for the import point with the typeof (IPlugin) contract. Our last step is to write the composition code, which we will put in the constructor of HomeController. After running the resulting code, we can observe the expected result (Fig. 6). Fig. 6.

    image





    image



    image
    The result of the work of MEF

    As you can see, after running ComposeParts, the Plugin property took on the value of an instance of the FirstPlugin class, as it was intended.

    Conclusion


    In this chapter, we got acquainted with the MEF framework, its purpose and the problems that it aims to solve. We examined the basic concepts of MEF and some of their features: import, export, composition, contracts. We built the first example based on the information received, which demonstrated the work of MEF in practice.

    In the next chapter, we will delve deeper into the framework, look at a more complex example with several plug-ins, and get acquainted with the concept of directories in MEF.

    Also popular now: