mef 枚举导出和架构 [英] mef enum exports and architecture

查看:26
本文介绍了mef 枚举导出和架构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 mef 制作我的插件子系统,但我几乎没有问题,因为我是 csharp 和 mef 的新手(

I want to make my plugin subsystem using mef but i have few question because i am newbie in csharp and mef (

我想做什么:

  1. 每个插件都可以创建自己的接口 IPlugin1、IPlugin2 ...
  2. 这些接口中的每一个都必须具有指定的函数加载、卸载
  3. 使用 mef 我想枚举所有导出并调用加载/卸载

问题:

一个.我的解决方案好不好?如果不好,我该如何改进(通过使用其他方法)?

a. Is my solution good and if no how can i improve it (by using something else)?

B.如何使用mef枚举所有导出并调用指定的接口函数?

b. How to enum all exports using mef and call specified interface function?

我会感谢所有链接和评论.谢谢大家.

I would appreciate for all links and critics. Thanks for all.

推荐答案

基于@m-y 的回答,我确实认为拥有一个通用界面是您可以采用的最佳设计.这是利用可应用于插件的一组通用操作的最简单方法.不过,我会考虑的是稍微改进一下:

Building on @m-y's answer, I do think having a common interface is the best design you can go with. It is the easiest way to leverage a common set of operations you could apply to your plugins. What I would consider though, is a slight refinement:

public interface IPlugin : IDisposable
{
    void Initialise();
}

通过强制实施Dispose 方法,您的部分可以自动受到CompositionContainer 的生命周期管理功能的控制.您所有的卸载代码都可以放在那里,这是一个示例插件:

By enforcing the Dispose method is implemented, you part can automatically be controlled by the lifetime management features of the CompositionContainer. All your unloading code can go in there, here is a sample plugin:

public interface ILogger : IPlugin
{
    void Log(string message);
}

[Export(typeof(ILogger))]
public class ConsoleLogger : ILogger
{
    void IPlugin.Initialise()
    {
        Console.WriteLine("Initialising plugin...");
    }

    public void Log(string message)
    {
        Console.WriteLine(message);
    }

    public virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            Console.WriteLine("Disposing plugin...");
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

Dispose 模式允许使用标准化的机制来清理您的代码.您的 CompositionContainer 实例将跟踪此项目,并在处置时对其进行清理.

The Dispose pattern allows a standardised mechanism for cleaning up your code. Your CompositionContainer instance will keep track of this item, and clean it up when it is disposed.

现在,我想描述的是 MEFContrib 中的一个很好的补充,称为拦截目录.这个目录允许你做的是注册拦截策略,它可以让你在返回到调用代码之前访问导出的值.一个这样的用途可能是在第一次导出实例时自动确保在基础 IPlugin 接口上调用 Initialise:

Now, what I wanted to describe is a nice addition in MEFContrib called the InterceptingCatalog. What this catalog allows you to do, is register interception strategies which could give you access to an exported value before it is returned to your calling code. One such use could be to automatically ensure that Initialise is called on the base IPlugin interface when the instance is being exported for the first time:

public class InitialisePluginStrategy : IExportedValueInterceptor
{
    public object Intercept(object value)
    {
        var plugin = value as IPlugin;
        if (plugin != null)
            plugin.Initialise();

        return value;
    }
}

让我们把这一切联系起来:

Let's tie all this up:

static void Main(string[] args)
{
    var catalog = new AssemblyCatalog(typeof(Program).Assembly);

    var configuration = new InterceptionConfiguration()
        .AddInterceptor(new InitialisePluginStrategy());

    var interceptingCatalog = new InterceptingCatalog(catalog, configuration);

    var container = new CompositionContainer(interceptingCatalog);

    var logger = container.GetExportedValue<ILogger>();

    logger.Log("test");

    Console.ReadKey();
}

如果您运行它,您会注意到我们的 ConsoleLogger 在我们第一次从容器中获取它时自动初始化.我们不需要担心它会再次初始化,它只会在创建导出的实例时这样做,这意味着它遵守单例和非单例场景.

If you run that, you'll notice our ConsoleLogger is automatically initialised the first time we get it from the container. We don't need to worry about it being initialised again, it will only do so when it is creating the exported instance, which means it obeys singleton and non-singleton scenarios.

此时您可能会认为这可能有点矫枉过正,但它实际上是一个非常优雅的解决方案,可以让您的部件自动启动,并在不再需要时进行处理.

You might be thinking at this point that this could be overkill, but its actually quite an elegant solution to enable your parts to be automatically started, and disposed of when no longer needed.

当然,如果您想对部件的初始化方式进行细粒度控制,您可以在自己编写的方法中管理这些,您只需要在这样做时考虑插件状态.

Of course, if you want fine grained control over how your parts are initialised, you could just manage these in a method you write yourself, you just need to consider the plugin state when you do so.

您可以在 Piotr Włodek 的博客

这篇关于mef 枚举导出和架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆