4

首先,简单的问题。

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

背景是我试图在 MEF 中实现发布者/订阅者模式。基本上,订阅者类这样做:

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

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

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

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

第二个问题

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

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

供参考

仅供参考,这是 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;
  }

}

4

2 回答 2

3

这可能无济于事,但部分本身可以在完全组合后收到通知:

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

}
于 2012-06-18T17:59:57.603 回答
1

您可以使用 MEF Contrib 中的 InterceptingCatalog(MEF Contrib 在 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);
于 2012-07-01T07:58:22.547 回答