Jul*_*anR 5 c# dll plugins appdomain .net-assembly
我们为一个产品建立了相当大的C#代码库,该产品已分成许多程序集以避免单个产品并强制执行某些代码质量标准(特定于客户的功能包含在特定于客户的程序集中,以保持“核心”通用且不受限制)取决于客户特定的业务逻辑)。我们在内部将这些插件称为“插件”,但它们更多是构成整个产品的模块。
运作方式是将这些模块的DLL复制到目录中,然后应用程序运行时(ServiceStack IIS Web应用程序或基于Quartz的控制台应用程序)会对Assembly.LoadFile不在当前程序集列表中的每个模块执行一个操作。已加载(AppDomain.CurrentDomain.GetAssemblies())。
这PluginLoader只会加载plugins.config文件中存在的程序集,但是我认为这与手头的问题几乎没有关系。
PluginLoader该类的完整代码:
https://gist.github.com/JulianRooze/9f6d1b5e61c855579203
这个...。有点。但是它很脆弱,并且遇到一个问题,即程序集从不同的位置(通常是从应用程序的/ bin /文件夹和插件目录)以这种方式两次加载。发生这种情况似乎是因为在PluginLoader调用该类时,AppDomain.CurrentDomain.GetAssemblies()(在启动时)不一定返回程序将自行加载的程序集的最终列表。因此,如果/ bin /中有一个尚未被程序使用的名为dapper.dll的程序集(核心和许多插件/模块的共同依赖项),则该程序集尚未被加载(换句话说, :它会延迟加载它们)。然后,如果该dapper.dll也由插件提供,PluginLoader将会看到它尚未加载,并将对其进行加载。然后,当程序使用其Dapper依赖项时,它将从/ bin /加载dapper.dll,现在我们已经加载了两个dapper.dll。
在大多数情况下,这似乎很好。但是,我们使用RazorEngine库,该库在您尝试编译模板时会抱怨名称相同的重复程序集。
在对此进行调查时,我遇到了一个问题:
有没有一种方法可以强制将所有引用的程序集加载到应用程序域中?
我尝试了接受的答案和Jon Skeet的解决方案。可接受的答案有效(尽管我还没有验证是否有任何奇怪的行为),但是感觉很讨厌。一方面,这也使程序尝试加载恰好在/ bin /中的本机DLL,这显然会失败,因为它们不是.NET程序集。因此,您现在必须尝试捕获该错误。如果/ bin /包含一些实际上不再使用的旧DLL,但现在无论如何都会加载,我也担心会有奇怪的副作用。那不是生产中的问题,而是开发中的问题(实际上,这整个问题在开发中比在生产中更多的是问题,但是解决此问题的附加健壮性在生产中也会受到赞赏)。
如前所述,我也尝试了Jon Skeet的答案,并且PluginLoader在该方法的类的Gist中可以看到我的实现LoadReferencedAssemblies。这有两个问题:
System.Runtime.Serialization找不到文件。我还使用托管扩展框架进行了简短的调查,但不确定是否适用。这似乎更旨在为提供一个用于加载组件并定义它们如何交互的框架,而我实际上只是对动态加载程序集感兴趣。
因此,考虑到“我想从目录中动态加载DLL的指定列表,而又没有加载重复程序集的机会”的要求,最佳解决方案是什么?:)
如果愿意的话,我愿意彻底检查插件系统的工作方式。
有几种方法可以解决此问题(将模块/插件部署在目录的层次结构中),坦率地说,您选择了最困难的方法。
在最简单的一种是添加所有的文件夹在你的私人探测路径的应用程序/ web.config中。然后,Assembly.LoadFile用Assembly.Load替换对的所有调用。这将使.NET程序集解析机制可以自动为您解析所有程序集。您将不需要加载引用的程序集,因为它们将在需要时自动加载。只需使用即可加载模块/插件Assembly.Load。
如果存在以下任一情况,则此方法的缺点:
AssemblyCatalog请注意,我对ServiceStack不熟悉。在ASP.NET中,可以使用该Assembly.Codebase属性加载在bin外部部署的程序集。
最后,看看Suzanne Cook的关于LoadFile与LoadFrom的博客条目。
| 归档时间: |
|
| 查看次数: |
3450 次 |
| 最近记录: |