我正在尝试按照此处建议的实现为我们的 WPF 程序实现插件架构。我希望我的插件位于与主程序文件夹不同的文件夹中。我已经让它只能部分工作。这是代码:
该计划是为每个插件提供自己的 StructureMap 注册表以覆盖默认的 StructureMap 注册表。
我目前正在使用的插件具有以下注册表,如您所见,我正在覆盖注册表IPrintProgramExecutor
以拦截和使用插件类型AutomationController
。它按预期工作:
public class PluginRegistry : Registry
{
public PluginRegistry()
{
this.ForConcreteType<AutomationController>()
.Configure
.Ctor<IPrintProgramExecutor>().Is(c=> c.GetInstance<PrintProgramExecutor>())
.Singleton();
this.For<IAutomationController>().Use(c => c.GetInstance<AutomationController>()).Singleton();
this.For<IPrintProgramExecutor>().Use(c => c.GetInstance<IAutomationController>()).Singleton();
//this.ForConcreteType<AutomationPlugin>()
// .Configure
// .Singleton();
this.For<IPluginBase>().Use<AutomationPlugin>();
}
}
AutomationPlugin
目前是这个存根:
public class AutomationPlugin : IPluginBase
{
public ViewModelBase ViewModel {
get { return viewModel; }
private set { viewModel = value; }
}
public ResourceDictionary View { get; }
private ViewModelBase viewModel { get; set; }
private ResourceDictionary viewDictionary = new ResourceDictionary();
public AutomationPlugin()
{
// do something meaningfull!
}
}
与IPluginBase
:
public interface IPluginBase
{
ViewModelBase ViewModel { get; }
ResourceDictionary View { get; }
}
添加注册表的类是这样的,pluginPath
扩展文件夹的路径在哪里:
public class PluginRegistryAdder : Registry
{
public PluginRegistryAdder(string pluginPath)
{
Scan( x =>
{
x.AssembliesFromPath(pluginPath);
x.LookForRegistries();
});
}
}
使用上面的代码实际绑定插件注册表的类是这样的:
public static class ExtensionManager
{
public static void RegisterPluginsInDic(string pluginPath, IContainer container)
{
var pluginRegistries = new PluginRegistryAdder(pluginPath);
container.Configure(_ => _.IncludeRegistry(pluginRegistries));
var whatIHave = container.WhatDoIHave(typeof(IPluginBase));
var plugins = container.Model.GetAllPossible<IPluginBase>(); // the IEnumberable plugins is empty although I am registering `AutomationPlugin` for it. Why?!
}
}
现在,如上所述,插件类型的拦截IPrintProgramExecutor
按预期工作。但由于某种原因container.Model.GetAllPossible<IPluginBase>()
,container.WhatDoIHave(typeof(IPluginBase))
并没有找到 plugin-type 的任何注册类型IPluginBase
。我已经尝试调用这些方法,IPrintProgramExecutor
并且肯定它们返回了具体类型。找了好久的原因,没找到。
任何想法为什么?这是否与我打了两次电话的事实有关,也许与我第一次打电话时container.Configure(...)
已经注册了一些东西有关?非常感谢您的帮助!IPringProgramExecutor
container.Configure(...)
更新:
- 切换到我的笔记本电脑后,以前有效的拦截不再有效。此外,我现在遇到一个异常,即
PluginRegistry
找不到我尝试注册的程序集之一:
StructureMap.StructureMapException:无法为注册表类型“Extensions.Automation.PluginRegistry”创建实例。详情请查看内部异常---> System.Reflection.TargetInvocationException: 异常已被调用的目标抛出。---> System.IO.FileNotFoundException:无法加载文件或程序集“Automation.Servers.Interfaces,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”或其依赖项之一。该系统找不到指定的文件。在 Extensions.Automation.PluginRegistry..ctor() ...
总而言之,这似乎是一个我无法弄清楚的路径问题。我怀疑,在运行时,程序会尝试从主路径加载插件注册表中的 DLL,但相应的 DLL/程序集驻留在扩展文件夹中。如何查看 StructureMap 尝试加载程序集Automation.Servers.Interfaces
以进行调试的位置?希望有人可以帮助我。我正在慢慢失去它。