欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

构建插件式的应用程序框架(六)-通讯机制

程序员文章站 2022-05-03 13:00:44
...
 前天发了构建插件式的应用程序框架(五)----管理插件这篇文章,有几个朋友在回复中希望了解插件之间是如何通讯的。

这个系列的文章写到这里,也该谈谈这个问题了,毕竟已经有了插件管理。不知道大家有没有注意到我在第四篇文章里谈到的服务容器(Service Container),Service是我所提到的插件式的应用程序框架的基础,我们也可以回头看看IApplication的接口定义,IApplication是派生于IServiceContainer。我把应用程序提供的相关的功能抽象成一个一个的Service,比如文档管理的,我们就抽象成IDocumentService,停靠工具栏管理功能抽象成IDockBarService,菜单管理的功能抽象成IMenuService,等等。我在第四篇文章里也提到了“我们在使用Service架构的时候,总是倾向于有一个根容器,各个Service容器构成了一个Service容器树,每一个节点的服务都可以一直向上传递,直到根部,而每一个节点请求Service的时候,我们总是可以从根节点获得。我把这个根节点比喻成一个服务中心,它汇总了所有可提供的服务,当某个对象要请求服务(GetService)只需要向根结点发送要获得的服务,根结点就可以把服务的对象传递给它。”

IApplication是从IServiceContainer接口派生出来的,而我们的应用程序主窗口又是从IApplication接口派生出来的,所以,我们的应用程序主窗口就是一个ServiceContainer。从IPlugin的定义来看,它有一个IApplication接口属性,这个IApplication属性是什么时候指定的呢,在第五篇文章的源代码里我们看到,当每一个Plugin被实例化的时候,由PluginService指定的,所以在每一个Plugin被Load之前,IApplication已经被指定,而代表这个IApplication接口的实例正是我们的应用程序主窗口,而它正是我们所需要的服务容器。一旦我们能够获得IApplication实例,我们就可以获得整个应用程序所提供的所有的服务。假设我们要获得文档服务,就可以使用Plugin的Application.GetService(typeof(IdocumentService))来得到文档服务的实例,接着我们就可以使用这个实例来完成某项功能,比如添加一个新文档等等,其实在第五篇文章的源代码就有这样代码:
private void CheckExistedPlugin()
{
    IPluginService pluginService = (IPluginService)application.GetService(typeof(IPluginService));
    if (pluginService != null)
    {
        List<String> nameList = new List<string>();
        String[] pluginNames = pluginService.GetAllPluginNames();
        nameList.AddRange(pluginNames);
        foreach (ListViewItem item in listView1.Items)
        {
            if (nameList.Contains(item.Text))
            {
                item.Checked = true;
            }
        }
    }
}

当然,要在插件中获得实例,你必须在应用程序里或者其他插件里实例化服务对象,然后添加到服务容器里,还拿上边的例子,我们在应用程序里实例化了PluginService,然后添加到了容器里,代码如下:
public MainForm()
{
    InitializeComponent();
    pluginService = new PluginService(this);
    serviceContainer.AddService(typeof(IPluginService), pluginService);
}

稍后,我会继续完善这个例子,做一个简单的多文档编辑器来做演示,并提供一些基础的服务,以便大家阅读。