0

我正在为需要健壮的自动化调度程序编写插件架构,因此我正在尝试执行 ASP.NET/IIS 样式的 AppDomains——即每个 AppDomain 都被真正视为其自己的不同应用程序,之间没有共享对象他们。

我正在设置ApplicationBase,ConfigurationFileShadowCopyFilesAppDomainSetup.

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

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

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

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

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

你怎么看?

4

1 回答 1

0

我不确定这是否能准确回答您的问题,但我们有一个类似的设置,其中我们有一个独立的子 AppDomain 和一个共享 DLL 文件夹,我们在不使用 AssemblyResolve 的情况下取得了成功。

我们的文件结构是:

[PathToApplication]\OurApplication.exe
[PathToApplication]\AddIns\[SharedAssemblies]\*.dll
[PathToApplication]\AddIns\[FirstAddIn]\*.dll
[PathToApplication]\AddIns\[SecondAddIn]\*.dll

方括号中的部分被实际路径替换。

在我们的例子中,共享程序集也由主 AppDomain 加载,因此我们在主 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)]在应用程序入口点上使用 set 运行它,并验证了 DLL 实际上是在内存中共享的(很容易出错并默默地阻止这种情况发生)。

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

于 2013-03-20T10:16:32.527 回答