我把我的问题分成了一个简短的版本,适用于手头很少的人.
精简版:
我需要一些具有提供者和消费者插件的系统架构.提供商应实施interface IProvider,消费者应实施IConsumer.执行的应用程序应该只知道IProvider和IConsumer.消费者实现可以向执行程序集(通过ServiceProcessor)询问哪些提供程序实现InterfaceX并获取List.这些IProvider对象应该被转换为InterfaceX(在使用者中),以便能够将使用者挂钩到InterfaceX定义的某些事件上.这将失败,因为执行程序集以某种方式不知道此InterfaceX类型(强制转换失败).解决方案是将InterfaceX包含在插件和执行程序集引用的某个程序集中,但这应该意味着对每个新的提供者/消费者对进行重新编译并且非常不受欢迎.
有什么建议?
长版:
我正在开发某种通用服务,它将使用插件来实现更高级别的可重用性.该服务包含使用提供者和使用者的某种Observer模式实现.提供者和使用者都应该是主应用程序的插件.让我首先通过列出我在解决方案中的项目来解释服务的工作原理.
项目A:用于托管所有插件和基本功能的Windows服务项目.TestGUI Windows窗体项目用于更轻松的调试.来自Project B的ServiceProcessor类的一个实例正在执行与插件相关的东西.此项目的子文件夹"Consumers"和"Providers"包含子文件夹,其中每个子文件夹分别包含一个使用者或提供者插件.
项目B:包含ServiceProcessor类的类库(在插件之间执行所有插件加载和调度等),IConsumer和IProvider.
项目C:链接到项目B的类库,由TestConsumer(实现IConsumer)和TestProvider(实现IProvider)组成.TestProvider实现了一个额外的接口(ITest,本身派生自IProvider).
这里的目标是消费者插件可以向ServiceProcessor询问它所拥有的提供者(至少实现IProvider).返回的IProvider对象应该被转换到它在IConsumer实现中实现的其他接口(ITest),以便使用者可以将事件处理程序挂钩到ITest事件.
当项目A启动时,将加载包含使用者和提供者插件的子文件夹.以下是我到目前为止遇到的一些问题并试图解决.
ITest用于驻留在Project C中的接口,因为这仅适用于TestProvider和TestConsumer所知道的方法和事件.一般的想法是保持项目A简单并且不知道插件彼此做什么.
使用项目C中的ITest和TestConsumer的Initialize方法中的代码将IProvider转换为ITest(当实现ITest的对象被称为IConsumer对象时,这不会在单个类库中失败)会发生无效的转换错误.通过将ITest接口放入项目A引用的项目B中,可以解决此错误.这是非常不受欢迎的,因为我们需要在构建新接口时重新编译项目A.
我试图将ITest放在由项目C引用的单个类库中,因为只有提供者和使用者需要知道这个接口,但没有成功:当加载插件时,CLR声明无法找到引用的项目.这可以通过挂钩当前AppDomain的AssemblyResolve事件来解决,但不知何故这似乎也是不需要的.ITest再次回到了B项目.
我尝试将项目C拆分为消费者和提供者的单独项目,并且都加载本身运行良好的程序集:两个程序集都驻留在Assemblies集合中或当前的AppDomain:程序集找到:Datamex.Projects.Polaris.Testing.Providers ,版本= 1.0.0.0,文化=中性公钥= 2813de212e2efcd3大会发现:Datamex.Projects.Polaris.Testing.Consumers,版本= 1.0.0.0,文化=中立,公钥= ea5901de8cdcb258
由于消费者使用提供者,因此从消费者到提供者进行了引用.现在,AssemblyResolve事件再次触发,表明它需要以下文件:AssemblyName = Datamex.Projects.Polaris.Testing.Providers,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = 2813de212e2efcd3
我的问题:这是为什么?这个文件已经加载了吗?为什么从IProvider到某些界面的演员我知道它实现了不可能?这可能是因为执行程序本身不知道这个接口,但不能动态加载?
我的最终目标:消费者插件向ServiceProcessor询问它实现接口x的提供商.提供程序可以转换为此接口x,而不执行程序集知道接口x.
有人可以帮忙吗?
提前谢谢,Erik
我终于设法在这里的一些人的帮助下构建了一个插件架构的工作解决方案,但现在出现了一个新问题.
我的托管应用程序使用它的app.config文件来执行程序集(这是一个Windows服务)的一些默认值.
每个插件应该能够从单独的插件设置文件加载它自己的设置,因为不应该让主机知道插件设置.在插件项目中,我还添加了一个app.config文件(带有一些设置和一个连接字符串),这样我就可以实例化Properties.Settings类并在插件代码中使用它的属性.
问题是当我更改插件的app.config中的设置(构建为plugin.dll.config)时,我无法在插件本身中看到这些更改,它仍然使用设计时设置.
有没有办法在每个插件中加载app.config设置,以便生成的Properties.Settings类可以工作?如果没有,还有另一种方法可以将基于app.config的设置文件加载到插件中吗?我打算在IPlugin界面中添加一个LoadConfiguration方法,这样每个插件都会加载它自己的设置.