完整的ASP.. net风格的AppDomain程序集隔离
本文关键字:AppDomain 程序集 风格 隔离 net ASP | 更新日期: 2023-09-27 18:03:50
我正在为一个自动化调度程序编写一个插件架构,它需要是健壮的,所以我试图做ASP。. net/iis风格的AppDomain——即,每个AppDomain都被视为自己独特的应用程序,它们之间没有共享对象。
我在AppDomainSetup
中设置ApplicationBase
, ConfigurationFile
和ShadowCopyFiles
。
在我为每个插件加载的自动化调度程序中有一个公共程序集——它处理加载插件的主程序集,捕获未捕获的异常,并记录日志。我发现这种方法有一些缺点:
-
通过将
ApplicationBase
设置为插件存储的位置,将不再解析公共程序集的任何依赖项(驻留在不同路径中)。我通过钩住AssemblyResolve
事件将其黑入工作,但这会导致其他问题。 -
有可能公共程序集和插件都引用了他们自己的同名程序集的副本——可能每个都有不同的版本。或者可能是名称相同但内容完全不同的程序集。重写
AssemblyResolve
,插件的副本将总是首先加载。 -
不是真的担心这个,但从安全的角度来看,我认识到插件有可能覆盖调度程序的依赖,导致它做一些邪恶的事情,或者反映到公共程序集并获得内部。
所以我决定,也许正确地做到这一点的唯一方法就是简单地不这样做——强制一个干净的分离,不加载任何程序集到AppDomain。我不知道最好的方法是什么,甚至不知道这是不是最好的方法。
你觉得怎么样?
我不确定这是否完全回答了你的问题,但我们有一个类似的应用程序设置,我们有独立的子AppDomains和共享dll文件夹,我们没有使用AssemblyResolve就成功了。
我们的文件结构是:
[PathToApplication]'OurApplication.exe
[PathToApplication]'AddIns'[SharedAssemblies]'*.dll
[PathToApplication]'AddIns'[FirstAddIn]'*.dll
[PathToApplication]'AddIns'[SecondAddIn]'*.dll
其中方括号中的部分替换为实际路径。
在我们的示例中,共享程序集也由主AppDomain加载,因此我们在主App.config
中设置如下:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="AddIns'[SharedAssemblies]" />
</assemblyBinding>
</runtime>
确保共享程序集不存在于主可执行文件旁边,否则它将从主可执行文件加载它们,这将无声地停止所有appdomain之间共享dll。
然后,对于每个加载项的AppDomain,我们将其配置为基本路径位于加载项文件夹和共享文件夹之上的文件夹,并设置私有bin路径,以便它以正确的顺序搜索正确的子文件夹:
var basePath = @"[PathToApplication]'AddIns";
var configFile = Path.Combine(
basePath,
addInFolder,
addInAssemblyName + ".dll.config");
var binPaths = new [] { "[SharedAssemblyFolder]", addInFolder };
setup = new AppDomainSetup
{
ApplicationBase = basePath,
ConfigurationFile = configFile,
LoaderOptimization = LoaderOptimization.MultiDomain,
PrivateBinPath = string.Join(";", binPaths),
PrivateBinPathProbe = string.Empty,
};
这样,它总是首先搜索共享文件夹,所以即使加载项提供了自己的同名DLL,它也会被忽略。
我们在应用程序入口点设置[System.LoaderOptimization(LoaderOptimization.MultiDomain)]
的情况下运行这个程序,并且已经验证了dll实际上是在内存中共享的(很容易犯一点错误,然后悄悄地阻止这种情况发生)。
希望对大家有所帮助。