Creating an MEF Export Instance

Firstly, a simple question.

Is it possible to get event when MEF (System.ComponentModel.Composition) creates an instance of the part? When this happens, I want to reflect the created object and connect various attributes. In Spring.Net, this is possible with the IObjectPostProcessor interface.

It is assumed that I am trying to implement the Publisher / Subscriber pattern in MEF. Basically the subscriber class does this:

 class MyContoller { [Command("Print")] public void Print() { ... } [Command("PrintPreview")] public void PrintPreview() { ... } } 

And I want to determine when an instance of MyController was created and connected to any methods that have a CommandAttribute .

A publisher, such as a menu item, will do Command.Get("Print").Fire() to post the aforementioned event.

Second question

Perhaps there is an alternative template in MEF that I miss !!!

I have seen several posts about MEF, Prism, and Aggregate events , but it looks rather complicated.

Fyi

For reference only, here is the original for the Spring.Net implementation:

 class CommandAttributeProcessor : IObjectPostProcessor { static ILog log = LogManager.GetLogger(typeof(CommandAttributeProcessor)); public object PostProcessAfterInitialization(object instance, string objectName) { foreach (MethodInfo methodInfo in instance.GetType().GetMethods()) { foreach (CommandAttribute attr in methodInfo.GetCustomAttributes(typeof(CommandAttribute), true)) { if (log.IsDebugEnabled) log.Debug(String.Format("Binding method '{0}.{1}' to command '{2}'.", instance.GetType().Name, methodInfo.Name, attr.CommandName)); Command command = Command.Get(attr.CommandName); command.Execute += (EventHandler) Delegate.CreateDelegate(typeof(EventHandler), instance, methodInfo); } } return instance; } public object PostProcessBeforeInitialization(object instance, string name) { return instance; } 

}

+4
source share
2 answers

You can use the InterceptingCatalog from the MEF Contrib ( MEF Contrib on codeplex or you can install it using nuGet) and implement the IExportedValueInterceptor interface to connect methods that have CommandAttribute:

 //using System.ComponentModel.Composition; //using System.ComponentModel.Composition.Hosting; //using MefContrib.Hosting.Interception; //using MefContrib.Hosting.Interception.Configuration; public class CommandAttributeProcessor : IExportedValueInterceptor { public object Intercept(object value) { foreach (MethodInfo methodInfo in value.GetType().GetMethods()) { foreach (CommandAttribute attr in methodInfo.GetCustomAttributes(typeof(CommandAttribute), true)) { // do something with command attribute } } return value; } } 

and when creating the MEF directory, you need to add the capture configuration with your hook (CommandAttributeProcessor) and wrap your directory in InterceptingCatalog as follows:

 InterceptionConfiguration interceptionConfiguration = new InterceptionConfiguration(); interceptionConfiguration.AddInterceptor(new CommandAttributeProcessor()); InterceptingCatalog interceptingCatalog = new InterceptingCatalog(assemblyCatalog, interceptionConfiguration); CompositionContainer container = new CompositionContainer(interceptingCatalog); 
+1
source

This may not help, but the part itself may receive a notification when it is fully composed:

Automatic method call after the part has been composed in MEF

In addition, you probably already know this (and it may not be entirely related to what you are trying to do), but you can decorate your exports and imports, as specific implementations are called. So you could export the class like this:

 [Export("Print", typeof(IPlugin))] [PartCreationPolicy(CreationPolicy.Shared)] class Print : IPlugin { . . . public Fire() { //Do something; } } class PrintMenuItem { IPlugin _plugin; [ImportingConstructor] PrintMenuItem([Import("Print", typeof(IPlugin)] plugin) { _plugin = plugin; } void Execute() { _plugin.Fire(); } } 
+3
source

All Articles