MEF实例化出口部分

时间:2012-06-18 17:41:49

标签: c# mef spring.net

首先,简单的问题。

当MEF(System.ComponentModel.Composition)创建部件的实例时,是否可以接收event? 当发生这种情况时,我想反思创建的对象并连接各种属性。在Spring.Net中,可以使用IObjectPostProcessor接口。

背景是我尝试在MEF中实现Publisher / Subscriber模式。基本上订阅者类这样做:

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

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

我想检测MyController何时被实例化并连接具有CommandAttribute的任何方法

发布商(例如菜单项)会Command.Get("Print").Fire()发布上述事件。

第二个问题

也许在MEF中有一种我缺少的替代模式!!!

我看过一些关于MEF, Prism and the Event Aggregate的帖子,但看起来相当复杂。

FYI

仅供参考,这是Spring.Net实现的原始内容:

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;
  }

}

2 个答案:

答案 0 :(得分:3)

这可能没有帮助,但部件本身可以在完全组合时收到通知:

Automatically call method after part has been composed in MEF

此外,您可能已经知道这一点(并且它可能与您尝试做的事情无关),但您可以装饰您的导出和导入,例如具体实现已命名。所以,你可以有一个像这样的导出类:

[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();
  }

}

答案 1 :(得分:1)

您可以使用MEF Contrib的InterceptingCatalog(MEF Contrib on codeplex或者您可以通过nuGet安装它)并实现IExportedValueInterceptor接口来连接具有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;
    }
}

在创建MEF目录时,需要在拦截器(CommandAttributeProcessor)中添加拦截配置,并将目录包装在InterceptingCatalog中,如下所示:

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