MEF - 加载/卸载插件时通知

时间:2011-09-26 13:13:47

标签: asp.net-mvc events mef

我有一个简单的asp mvc应用程序,它使用MEF,管理员可以访问一个路径来刷新目录编目和组成部分,但是我想知道如何做的一件事就是通知一些代码插件加载/卸载时。

场景是,当加载插件时,他们会注册他们需要的路由,但是当他们被卸载时我需要他们卸载他们的路由,因为后续的刷新尝试重新注册路由并且它会发生炸弹。

我可以从MEF对象中找到任何事件吗?

插件容器类似于:

[ImportMany(typeof(ISomePluginInterface))]
IEnumerable<ISomePluginInterface> Plugins {get; private set;}

每个ISomePluginInterface都有类似的内容:

public interface ISomePluginInterface
{
   public void PluginLoaded();
   public void PluginUnloaded();
}

1 个答案:

答案 0 :(得分:0)

这在理论上与此Stackoverflow questionthis was my answer类似。在您的情况下,您有类似的需求,您希望在启动插件时触发事件,并在不再需要时进行清理。

使用相同的概念,您可以使用InterceptingCatalog来注册路由,但我不会将其作为接口定义的明确部分来执行此操作,而是需要查看组件的适合方式作为一个整体,例如,如果注册路由的操作不会用于所有插件,那么它们在接口定义中存在的目的是什么。您可以将路由注册分解为单独的接口IRouteRegistrar,并使用拦截策略在第一次使用插件时自动调用相应的注册方法,例如,我可以将接口分解为:

public interface IPlugin
{
  void SomeOperation();
}

public interface IRouteRegistrar : IDisposable
{
  void RegisterRoutes();
}

后一个界面执行注册路由的工作,我们使用Dispose模式确保在完成后清理它。因此,示例插件可能类似于:

[Export(typeof(IPlugin))]
public class MyPlugin : IPlugin, IRouteRegistrar
{
  public void SomeOperation() { }

  public void RegisterRoutes()
  {
    // Register routes here...
  }

  protected virtual Dispose(bool disposing)
  {
    if (disposing)
    {
      // Unregister routes here...
    }
  }

  void IDisposable.Dispose()
  {
    Dispose(true);
  }
}

我只导出为IPlugin,但我确保我的插件也实现了IRouteRegistrar。我们使用它的方式是采用策略:

public class RouteRegistrarStrategy : IExportedValueInteceptor
{
  public object Intercept(object value)
  {
    var registrar = value as IRouteRegistrar;
    if (registrar != null)
      registrar.RegisterRoutes();

    return value;
  }
}

现在,只有插件支持该接口才会注册路由。这也使您可以将路由注册接口应用于可以以不同方式使用的其他插件。你获得了更多的灵活性。要在代码中使用该策略,您需要将MefContrib项目添加到您的应用中,并进行更多的连接:

var catalog = new DirectoryCatalog(".\bin");
var config = new InterceptionConfiguration().AddInterceptor(new RouteRegistrarStrategy());

var interceptingCatalog = new InterceptingCatalog(catalog, configuration);
var container = new CompositionContainer(interceptingCatalog);