Introduction to the Managed Extensibility Framework
The purpose of this quick start is to familiarize you with the Managed Extensibility Framework. At the end of this quick start, you will be able to describe what the Managed Extensibility Framework (MEF) is, reasons you might use it, and the costs and risks
associated with applying MEF to your projects. You will know how to add MEF to your own .NET project.
Duration: 5 Minutes
- The Managed Extensibility Framework (MEF)
- System.ComponentModel.Composition namespace
The Managed Extensibility Framework (MEF) facilitates the creation of modular and extensible applications. It provides discovery and composition capabilities, a standard way to host and consume extensions, and meta-data to facilitate filtering and querying
of application components.
What do discovery and composition provide? One common problem that the developer must solve is how to provide global access to classes that deliver services such as configuration information, database access or even caching strategies to the application. Often,
developers use a combination of singleton, locator, and/or factory patterns to resolve instances. MEF solves this problem by allowing the developer to tag the responsible class as an export. Anywhere in the application this class is required, the developer
can provide an “import.” MEF will discover the class that is needed by examining the export tag then will compose it for the class that needs it via the import tag. This is just one example of problems MEF can help solve. While MEF addresses a variety of issues,
the most common reasons for using MEF include:
- Dependency injection / inversion of control – in applications that follow principles of loose coupling, code is written against contracts and interfaces, not concrete instances of classes. The challenge then becomes handling the implementation of
the contract or interface. This is often done either via a “locator” class which uses a “bootstrapper” to bind concrete classes to interfaces. MEF solves this problem by allowing implementations to be tagged as exports. Consumer classes simply reference imports
and MEF will glue the implementation/export to the contract/import.
- Lifetime management of classes (i.e. “singleton” verses multiple instances) – the singleton pattern often requires modifying a class to hide the constructor and provide a mechanism for accessing the singleton. With MEF, the class can be written as
any typical “instanced” class. There is no need to change how the class is written to accommodate how it will be accessed. MEF provides lifetime management services, which means when a class is declared as an export for the application, it can also specify
whether or not a single copy or a new instance will be provided any time it is imported. This allows lifetime management to become an implementation detail rather than part of the class design itself.
- Management of configuration data – MEF makes it easy to provide configuration data to an application. The configuration items may be defined as an interface that is imported by the classes that need them. The implementation of the contract can scan
files, isolated storage, registries, configuration files, or whatever else is needed to provide the configuration information and then export those values to application. The classes requiring configuration information don’t need to be aware of how that configuration
information is provided, as they simply import the interface and access the values.
- A reliable factory for components with dependency hierarchies – in some applications it is necessary to create multiple instances of certain classes. These classes may in turn have several dependencies to other classes. This can often require complicated
factory classes that are responsible for finding various services and passing them into new classes via constructors or by setting properties. MEF will do this automatically. A factory class is provided that provides the means to generate a new instance when
needed, and MEF will wire in all dependencies hierarchically down the chain.
- Finding and executing multiple implementations of common interfaces / contracts – the classic case for extensions is to provide a common contract that plug-ins must implement so the host program can communicate with the plug-in without knowing the
details of the underlying implementation. MEF allows you to import multiple implementations of the same contract to manage as many plug-ins or extensions as are needed.
- Strongly-typed metadata to classify, query, and filter application components – as a complement to the ability to provide multiple implementations, you can also tag these implementations with metadata. Whether you are providing a service, a user
control, or any other type of implementation, metadata can describe the capabilities of the implementation. The host can query metadata and use the implementations based on the context of the host application.
- Lazy instantiation of components – whether you need to query metadata to decide if you are going to use an implementation or simply want to wait to create an instance of a class, MEF uses the new .NET Lazy class and only produces an instance when
- Stable composition of external plug-ins – MEF provides “stable composition” which means it will not compose an extension if dependencies are missing or construction of the instance fails. This allows more stability in the host application and insulation
against plug-ins that are missing dependencies.
- Application modularity – MEFs composition capabilities allow for highly modular applications. Parts that satisfy contracts, extensions, and plug-ins can reside in separate DLLs and XAP files and are easily re-used between and across applications.
- Dynamic loading of components in the host application – one of the more powerful features of MEF is the ability to dynamically load assemblies. This allows extensions and plug-ins to be loaded at run-time on-demand.
When making your decision to use MEF you should weigh the benefits of the services it provides with the risks it may introduce to your project. These risks include:
- Size of the assembly (Silverlight only) – MEF adds several DLLs to the main XAP distribution for Silverlight applications
- Overhead of discovery and composition – MEF uses reflection to scan assemblies for types and exports and to generate instances. This can cause overhead when composing a dependency tree.
- Added points of failure – because MEF requires the use of parts with imports and exports, and allows for metadata filtering of imports, developers must manage their classes appropriately to follow the correct attribution or naming convention based
on the provider being used
- Increased requirements for troubleshooting and debugging – when MEF fails to compose/import an implementation, additional effort may be required to inspect the MEF hierarchy and determine why imports are failing
- Design-time vs. run-time considerations when using WPF and Silverlight in Blend and Visual Studio 2010 – special consideration must be made for how the built-in designer (Cider) in Visual Studio 2010 and Blend to ensure your classes are “Blend-friendly”
and can render appropriately in the designer.
Including MEF in your .NET Framework 4.0 is simple and easy. You simply add a reference to System.ComponentModel.Composition from the .NET tab in the add references dialog. If you are using Silverlight, you might also reference System.ComponentModel.Composition.Initialization
(this will be explained in a separate quick start).
During this quick start, you learned:
- What is the Managed Extensibility Framework?
- When should I use the Managed Extensibility Framework?
- What are the risks and costs associated with using the Managed Extensibility Framework?
- How do I include the Managed Extensibility Framework in my own project?