I am trying to add plugin extensibility to my C# application using the Managed Extensibility Framework (MEF) framework, and so far it is going ok; I have my main/host application loading plugins from a defined folder, and can call their methods etc. from the main application. Both the host application and the plugins reference a seperate dll assembly which contains the interfaces common to all projects.
This is working fine and I can call/interact with the plugins from the main application. However, I also would like to be able to interact with the host application from the plugins, but can't seem to find out how this is done.
I would like to be able to get/set/execute exported properties and methods in the main app from my plugins. Currently I am only able to 'speak' to the plugins from the main app, not the other way around as well.
My code thus far:
Interface DLL
namespace MefContracts
{
[InheritedExport]
public interface IPlugin
{
String DoWork();
}
public class Class1
{
public IPlugin plugin { get; set; }
}
}
Main/Host Application
namespace MyMEF
{
class clsMEF
{
private CompositionContainer _container;
[Import(typeof(MefContracts.IPlugin))]
public MefContracts.IPlugin plugin;
public clsMEF()
{
Compose();
}
void Compose()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog("..\\..\\Extensions"));
_container = new CompositionContainer(catalog);
try
{
this._container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
}
void Main()
{
clsMEF myMef = new clsMEF();
MessageBox.Show(myMef.plugin.DoWork());
}
}
Plugin
namespace MefPlugin
{
[Export]
public class Class1 : MefContracts.IPlugin
{
public String DoWork()
{
return "Plugin called";
}
}
}
You could add a host interface in the contracts assembly. For example:
[InheritedExport]
public interface IHost
{
string Version { get; }
}
Then add a property of type IHost to the IPlugin interface:
[InheritedExport]
public interface IPlugin
{
IHost Host { get; }
String DoWork();
}
Finally each plug-in will need to decorate the Host property with MEF's ImportAttribute:
[Import(typeof(IHost))]
public IHost Host { get; }
After much playing and trial and error, I found the issue I was having was I had not added the current executing assembly (System.Reflection.Assembly.GetExecutingAssembly()
) to the host's assembly catalogue along with the plugin's assemblies.
Many thanks to @PanosRontogiannis who got me on the right lines - that answer worked brilliantly once the assembly was properly added.
Here is the working code for others in need:
Interface DLL
using System.ComponentModel.Composition;
namespace MefContracts
{
[InheritedExport]
public interface IPlugin
{
String Work(String input);
}
[InheritedExport]
public interface IHost
{
string Version { get; }
}
}
Host Application
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace MyMEF
{
[Export]
public class Class1 : MefContracts.IHost
{
public String Version
{
get { return "v1.00"; }
}
}
class clsMEF
{
private CompositionContainer _container;
[Import(typeof(MefContracts.IPlugin))]
public MefContracts.IPlugin plugin;
public clsMEF()
{
Compose();
}
void Compose()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog("..\\..\\Extensions"));
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); // <-- THIS WAS THE MISSING PIECE
_container = new CompositionContainer(catalog);
try
{
this._container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
}
static class Program
{
static void Main()
{
clsMEF myMef = new clsMEF();
MessageBox.Show(myMef.plugin.Work("My Input"));
}
}
}
Plugin
using System.ComponentModel.Composition;
namespace MefPlugin
{
[Export]
public class Class2 : MefContracts.IPlugin
{
[Import(typeof(MefContracts.IHost))]
public MefContracts.IHost Host;
public String Work(String input)
{
return "Plugin Called (Input: " + input + "). Host Application Version: " + input + Host.Version;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With