【发布时间】:2019-05-24 11:38:18
【问题描述】:
背景
我有一个在 .Net Core 2.2 上运行的大型旧 C# 应用程序,我正在尝试向它添加“hotbin”功能。我的意思是,假设我的应用程序的入口点是 A.dll,而 A.dll 依赖于 B.dll(例如,B.dll 被 A.dll 的 .csproj 文件引用),并且 A.dll 也会加载(通过 Activator.CreateInstance)来自 C.dll 的类。因此,包含完整的已部署应用程序的文件夹如下所示:
/root/
|
+-A.dll
+-B.dll
+-C.dll
也就是说,所有 dll 都在同一级别上,.NET 可以毫无问题地找到 A.dll 的依赖项。这个“hotbin”功能背后的想法是我想定义一个特殊的文件夹,将 dll 放在那里,反弹应用程序,并让应用程序加载这些 dll 而不是 root 中的等效文件。所以,回到前面的例子,假设我的文件夹结构是这样的:
/root/
|
+-A.dll
+-B.dll
+-C.dll
+-/hotbin/
|
+-B.dll
当我启动 A.dll 时,我希望它从 /hotbin/ 文件夹加载 B.dll,而不是从 /root/ 文件夹加载 B.dll。
为什么我需要这个
此应用在 docker 容器中运行。如果我想测试一个错误修复,我宁愿将 dll 复制到一个文件夹中并反弹容器,然后创建一个带有错误修复的新 docker 映像并重新部署它。
我的尝试
向 A.runtimeconfig.json 添加“alternateProbingPath”。起初这似乎可行,但在从 A.dll 的 deps.json 加载所有 dll 后,应用程序在从这些 dll 加载依赖 dll 时崩溃。不确定每个 dll 是否需要为它自己的依赖项设置一个 alternateProbingPath,如果他们这样做了,那么这是一个不可行的,因为这个应用程序中有很多 dll。
-
将所有依赖的 dll 移动到 /local/ 文件夹并编写一个“A.Hotbin.dll”,它在 Activator.CreateInstance-ing A.dll 之前附加到 AssemblyResolve 事件并将控制权传递给它。
在此设置中,应用的文件夹如下所示:
/root/
|
+-A.hotbin.dll
+-A.dll
+-/local/
|
+-B.dll
+-C.dll
A.hotbin.dll 将拦截所有程序集解析失败(这种情况总是会发生,因为没有一个 dll 与 A.dll 位于同一文件夹中),检查该 dll 是否存在于 hotbin 文件夹中,然后如果它没有加载 /local/ 中的那个。同样,这几乎可以正常工作,但是在加载前几个 dll 后,应用程序会崩溃。没有堆栈跟踪,什么都没有。只是一个崩溃。附加调试器没有帮助,因为调试器导致崩溃更早发生。
- 将所有依赖的 dll 移动到 /local/ 文件夹并修改 A.hotbin.dll 以在启动时将该文件夹中的所有 dll 加载到当前 AppDomain 中。这不起作用,因为 AppDomain.Load() 采用程序集名称,而不是路径,并且它希望这些程序集位于正常位置,即 A.hotbin.dll 旁边。
还有其他建议吗?还是有其他方法可以做到这一点?我曾想过只使用 docker cp,但问题是我需要在新的 dll 中终止应用程序以 cp,而 K8S 会自动重启它。
【问题讨论】: