5

我正在为 .NET 3.5 应用程序(WinForms)设计一个简单的插件框架。

我们当前的应用程序需要开始支持在编译时应用程序未知的不同“插件”/“扩展”的动态加载和“挂钩”。

这些扩展将被“挂钩”到应用程序的不同区域,例如添加为某些类的事件处理程序。

例如(简化):

public class SomeSystem
{
     public event Action<string> Completed;

     public event Action<string> Failed;

     public event Action<string> Stopped;
}

我想要的一个用例是让开发人员能够在插件程序集中为此类事件定义处理程序,而无需让应用程序知道它们。

据我所知,IoC 容器允许在运行时动态发现对象并将它们注册到容器中。

IoC 容器是否也能够为我执行此挂钩到各种事件?或者如果没有这样的框架,这项任务是否更容易完成?

如何设计如何为这样的任务集成 IoC 容器?(假设有多个扩展点,比如不同的事件可以用来注册)。

我发现自己在问一些问题:

  1. 插件本身提供注册方法来进行注册是否常见?
  2. 国际奥委会应该注册吗?(通常是怎么做的?)
  3. 使用 IoC 容器时如何轻松定义扩展点?
4

2 回答 2

5

您可能想查看MEF。它允许您提出所有问题。它使用的术语(ComposableParts、Exports 等)最初令人困惑,但使用起来非常简单。

插件本身提供注册方法来进行注册是否常见?

MEF 使应用程序完成查找和注册插件的工作。该插件只需要实现一个声明“我是一个可以做X的插件”的接口。

国际奥委会应该注册吗?(通常是怎么做的?)

将使用 MEF 插件的应用程序能够指定它将如何加载插件。这可以通过在目录中搜索 DLL、读取配置文件以获取程序集名称列表、检查 GAC - 任何东西。它是完全可扩展的(您可以编写自己的搜索类)

使用 IoC 容器时如何轻松定义扩展点?

MEF 使用接口来定义应用程序和插件之间的契约。

于 2012-09-12T13:27:56.320 回答
0

这个答案将特定于我的容器。

我们当前的应用程序需要开始支持在编译时应用程序未知的不同“插件”/“扩展”的动态加载和“挂钩”。

为了能够做到这一点,您必须定义一些您放置在类库中的扩展接口,这些接口将在您的应用程序和所有插件之间共享。

例如,如果您希望您的应用程序能够向应用程序菜单添加内容,您可以创建以下界面:

class ApplicationMenu
{
    // The "File" menu
    IMenuItem File { get; }
}

interface IMenuRegistrar
{
    void Register(ApplicationMenu menu);
}

这意味着您的插件可以创建以下类:

[Component]
public class CoolPluginMenuRegistrar : IMenuRegistrar
{
    public void Register(ApplicationMenu menu)
    {
        menu.File.Add("mnuMyPluginMenuName", "Load jokes");
    }
}

我的容器使用该[Component]属性,以便它可以发现并自动为您注册类。

注册上述所有扩展点所需要做的就是:

public class Program
{
    public static void Main(string[] args)
    {
        var registrar = new ContainerRegistrar();
        registrar.RegisterComponents(Lifetime.Transient, Environment.CurrentDirectory, "MyApp.Plugin.*.dll");
        var container = registrar.Build();

        // all extension points have been loaded. To load all menu extensions simply do something like:

        var menu = GetMainMenu();
        foreach (var registrar in container.ResolveAll<IMenuRegistrar>())
        {
            registrar.Register(menu);
        }
    }
}

这些扩展将被“挂钩”到应用程序的不同区域,例如添加为某些类的事件处理程序。据我所知,IoC 容器允许在运行时动态发现对象并将它们注册到容器中。

是的。你得到了这一切。

IoC 容器是否也能够为我执行此挂钩到各种事件?或者如果没有这样的框架,这项任务是否更容易完成?

是的。我有一个内置的事件机制。将事件类(常规 .NET 类放在共享类库中)。通过实现一个接口来简单地订阅它们:

[Component]
public class ReplyEmailNotification : ISubscriberOf<ReplyPosted>
{
    ISmtpClient _client;
    IUserQueries _userQueries;

    public ReplyEmailNotification(ISmtpClient client, IUserQueries userQueries)
    {
        _client = client;
        _userQueries = userQueries;
    }

    public void Invoke(ReplyPosted e)
    {
        var user = _userQueries.Get(e.PosterId);
        _client.Send(new MailMessage(user.Email, "bla bla"));
    }
} 

并发布事件:

DomainEvent.Publish(new ReplyPosted(user.Id, "This is a subject"));

这些事件可以由任何插件处理,只要它们:

  1. 可以访问事件类
  2. 已在容器中注册([Component]或手动注册)
  3. 工具ISubscriberOf<T>

插件本身提供注册方法来进行注册是否常见?

是的。通过在共享程序集中定义为扩展点的不同接口。

国际奥委会应该注册吗?(通常是怎么做的?)

是的。如果容器提供它。

使用 IoC 容器时如何轻松定义扩展点?

您可以在此处更详细地了解它:http: //www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container

于 2012-09-12T14:56:48.217 回答