我正在为.NET 3.5应用程序(WinForms)设计一个简单的插件框架a。
我们当前的应用程序需要开始支持不同的“插件”/“扩展”的动态加载和“挂钩”,这些插件在编译时是应用程序所不知道的。
这些扩展将被“链接”到应用程序的不同区域,例如作为特定类的事件处理程序的aded。
例如(简化):
public class SomeSystem
{
public event Action<string> Completed;
public event Action<string> Failed;
public event Action<string> Stopped;
}我想要的一个用例是,开发人员能够在插件程序集中为此类事件定义处理程序,而不让应用程序了解它们。
据我所知,IoC容器允许在运行时动态地发现对象并在容器中注册它们。
IoC容器也能为我连接到各种事件吗?或者,如果没有这样的框架,这项任务更容易完成吗?
如何设计如何为这样的任务集成IoC容器?(假设有多个扩展点,例如可以用来注册的不同事件)。
我发现自己在问一些问题:
发布于 2012-09-12 13:27:56
您可能想看看MEF。它允许你询问的所有事情。它使用的术语(ComposableParts、Exports等)最初是令人困惑的,但使用起来非常简单。
插件本身提供了一个寄存器方法来进行注册,这很常见吗?
MEF让应用程序完成查找和注册插件的工作。这个插件只需要实现一个接口,上面写着"I是一个可以做X的插件“。
IoC应该注册吗?(这通常是怎么做到的?)
使用MEF插件的应用程序能够指定如何加载插件。这可以通过搜索DLL目录、读取程序集名称列表的配置文件、检查GAC -任何内容。它是完全可扩展的(因为您可以编写自己的搜索类)
在使用IoC容器时,如何容易地定义扩展点?
MEF使用接口来定义应用程序和插件之间的契约。
发布于 2012-09-12 14:56:48
这个答案将专门针对我的容器。
我们当前的应用程序需要开始支持不同的“插件”/“扩展”的动态加载和“挂钩”,这些插件在编译时是应用程序所不知道的。
要做到这一点,您必须定义一些扩展接口,这些接口放置在类库中,这些类库将在应用程序和所有插件之间共享。
例如,如果您希望您的应用程序能够向应用程序菜单添加内容,您可以创建以下接口:
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);
}
}
}这些扩展将被“链接”到应用程序的不同区域,例如作为特定类的事件处理程序的aded。据我所知,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"));事件可以由任何插件处理,只要它们:
[Component]或手动注册)ISubscriberOf<T>插件本身提供了一个寄存器方法来进行注册,这很常见吗?
是啊。通过在共享程序集中定义为扩展点的不同接口。
IoC应该注册吗?(这通常是怎么做到的?)
是。如果容器提供的话。
在使用IoC容器时,如何容易地定义扩展点?
您可以在这里更详细地了解它:http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container
https://stackoverflow.com/questions/12389163
复制相似问题