Archive
HowTo: Use MEF to implement import/export etc. plugin architecture
Copying here my comment at a discussion on the GraphX project:
https://github.com/panthernet/GraphX/pull/15
in case it helps somebody in using MEF (Managed Extensibility Framework) in their software’s architecture
——–
Using static classes instead of interfaces can mean though that you need to use reflection to call them (e.g. if you wan to have a list of export plugins).
Instead can keep interfaces and make use of MEF to locate import/export and other plugins (you can have some class attribute there that mark the class as a GraphXExporter and MEF can be asked then to give you interface instances from classes that have that attribute.)
see usage at
http://clipflair.codeplex.com/SourceControl/latest#Client/ClipFlair.Windows/ClipFlair.Windows.Map/MapWindowFactory.cs
//Project: ClipFlair (http://ClipFlair.codeplex.com)
//Filename: MapWindowFactory.cs
//Version: 20140318using System.ComponentModel.Composition;
namespace ClipFlair.Windows.Map
{//Supported views
[Export("ClipFlair.Windows.Views.MapView", typeof(IWindowFactory))]
//MEF creation policy
[PartCreationPolicy(CreationPolicy.Shared)]
public class MapWindowFactory : IWindowFactory
{
public BaseWindow CreateWindow()
{
return new MapWindow();
}
}}
//Project: ClipFlair (http://ClipFlair.codeplex.com)
//Filename: ImageWindowFactory.cs
//Version: 20140616using System.ComponentModel.Composition;
using System.IO;namespace ClipFlair.Windows.Image
{//Supported file extensions
[Export(".PNG", typeof(IFileWindowFactory))]
[Export(".JPG", typeof(IFileWindowFactory))]
//Supported views
[Export("ClipFlair.Windows.Views.ImageView", typeof(IWindowFactory))]
//MEF creation Policy
[PartCreationPolicy(CreationPolicy.Shared)]
public class ImageWindowFactory : IFileWindowFactory
{public const string LOAD_FILTER = "Image files (*.png, *.jpg)|*.png;*.jpg";
public static string[] SUPPORTED_FILE_EXTENSIONS = new string[] { ".PNG", ".JPG" };
public string[] SupportedFileExtensions()
{
return SUPPORTED_FILE_EXTENSIONS;
}public BaseWindow CreateWindow()
{
return new ImageWindow();
}}
}
to get the first plugin that supports some contract (I get that contract name from the serialization file [using DataContracts]) for a loaded view, or that supports some file extension for a file dropped inside a component, I do:
protected static IWindowFactory GetWindowFactory(string contract)
{
Lazy<IWindowFactory> win = mefContainer.GetExports<IWindowFactory>(contract).FirstOrDefault();
if (win == null)
throw new Exception(BaseWindowStrings.msgUnknownViewType + contract);
else
return win.Value;
}protected static IFileWindowFactory GetFileWindowFactory(string contract)
{
Lazy<IFileWindowFactory> win = mefContainer.GetExports<IFileWindowFactory>(contract).FirstOrDefault();
if (win != null)
return win.Value;
else
return null;
}