【发布时间】:2018-11-12 13:00:21
【问题描述】:
我正在从程序集名称的数据库表中动态加载程序集,它将规则插入规则引擎。这个想法是我们可以通过开发新规则来扩展功能,而无需重新编译和部署整个套件。
有一个 MVC Web 应用程序和一个 WCF 桌面应用程序共享大量代码,包括我在这里描述的 RulesRunner 类。
这段代码在RulesRunner类的构造函数中
rules = rulesEngineRepository.GetRules(x => x.Enabled);
foreach (var rule in rules)
{
var ruleAssembly = Assembly.LoadFrom($"{rule.AssemblyName}.dll");
var installerType = ruleAssembly.GetType("RulesEngine.Rules.RulesInstaller");
var installer = Activator.CreateInstance(installerType) as IWindsorInstaller;
container.Install(installer);
}
RulesRunner 类不是动态加载的,它被编译为 MVC 和 WCF 代码中的普通引用。
在 WCF 案例中,这一切都完全按照预期工作。加载程序集,创建一个实例,当规则引擎在其他地方触发时,它完美地使用以这种方式加载的规则。
在 MVC Web 应用程序中,此代码从 Activator.CreateInstance 行返回空值,因此在调用它时会进一步失败。我一生都无法弄清楚这里发生了什么不同。
如果我在调用 container.Install(installer) 后检查变量,我可以看到变量安装程序报告“'installer' 引发了 'System.IO.FileNotFoundException' 类型的异常”。
但是但是但是...installerType 具有所有正确的信息和值。这就像它找到了执行 LoadFrom 的 DLL,但是当它尝试进一步实例化它的两行代码时却无法再次找到它。
【问题讨论】:
-
根据我的经验,程序集解析和加载可能很麻烦,如果您的用例可能使用
Assembly.Load(byte[])重载,您可能可以跳过所有这些。 -
@thehennyy 如果我改用 var ruleAssembly = Assembly.Load(File.ReadAllBytes($"{rule.AssemblyName}.dll"));然后发生完全相同的事情。
-
然后您加载的程序集中的某些代码引用了另一个尚未加载且可能找不到的程序集。您可以尝试为程序集/类型加载事件注册一个事件处理程序并从那里进行调试。您是否确保两个项目都是针对完全相同的程序集编译的(同时没有重新编译)?
标签: .net wcf model-view-controller reflection