完整的ASP.NET风格的AppDomain程序集隔离

时间:2013-03-14 16:25:17

标签: c# appdomain

我正在为自动化调度程序编写一个插件架构,它需要很强大,所以我正在尝试使用ASP.NET / IIS风格的AppDomain - 即每个AppDomain都被视为自己独特的应用程序而没有他们之间共享对象。

我在ApplicationBase中设置了ConfigurationFileShadowCopyFilesAppDomainSetup

我为每个插件加载了自动化调度程序中的一个通用程序集 - 它处理加载插件的主程序集,捕获未捕获的异常和日志记录。我发现这种方法存在一些缺点:

  • 通过将ApplicationBase设置为存储插件的位置,将不再解析公共程序集(位于不同路径中)的任何依赖关系。我通过挂钩AssemblyResolve事件将其破解为工作,但这会导致其他问题。

  • 公共程序集和插件都可能引用它们自己的同名程序集的副本 - 可能每个都有不同的版本。或者可能是具有相同名称但内容完全不同的程序集。覆盖AssemblyResolve,将始终首先加载插件的副本。

  • 并不是真的担心这个问题,但是从安全的角度来看,我认识到插件可能会覆盖调度程序的依赖关系,导致它做一些邪恶的事情,或者反映到公共程序集中并获得内部结构

所以我已经决定,或许正确地做到这一点的唯一方法就是不要这样做 - 强制清除分离并且不将任何程序集加载到AppDomain中。我不确定最好的方法是什么,或者即使这是最好的方法。

您怎么看?

1 个答案:

答案 0 :(得分:0)

我不确定这是否完全回答了您的问题,但我们在应用程序中有类似的设置,其中我们有独立的子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实际上是在内存中共享的(很容易让它稍微出错并默默地阻止这种情况发生)。

希望这在某种程度上有所帮助。