背景
我在.Net Core 2.2上运行了一个大型的旧C#应用程序,我正在尝试向其中添加“ hotbin”功能。我的意思是说我的应用程序的入口点是A.dll,而A.dll依赖于B.dll(例如,A.dll的.csproj文件引用了B.dll),并且A.dll也加载了(通过Activator.CreateInstance)C.dll中的类。因此,包含完整的已部署应用程序的文件夹如下所示:
/root/
|
+-A.dll
+-B.dll
+-C.dll
也就是说,所有dll都处于同一级别,.NET定位A.dll的依存关系没有问题。此“ hotbin”功能背后的想法是,我想定义一个特殊的文件夹,在其中放置dll,启动应用程序,并让应用程序加载这些dll,而不是在根目录中加载等效的dll。因此,回到上一个示例,假设我的文件夹结构如下所示:
/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是否需要为其自身的依赖项提供alternativeProbingPath,如果它们确实需要,则这是一个入门,因为此应用程序中有很多dll。
将所有依赖的dll移动到/ local /文件夹,并在Activator.CreateInstance-ing A.dll并将控制权传递给它之前,编写一个附加到AssemblyResolve事件的“ A.Hotbin.dll”。
在此设置中,应用程序的文件夹如下所示:
/root/
|
+-A.hotbin.dll
+-A.dll
+-/local/
|
+-B.dll
+-C.dll
A.hotbin.dll将拦截所有程序集解析故障(由于没有dll与A.dll放在同一个文件夹中,因此总是会发生此错误),请检查dll是否存在于hotbin文件夹中,并如果没有将其加载到/ local /中。再次,这几乎可以工作,但是在加载前几个dll之后,应用程序将崩溃。没有堆栈跟踪,什么都没有。只是崩溃。附加调试器无济于事,因为调试器导致崩溃更早发生。
还有其他建议吗?还是有其他方法可以做到这一点?我曾考虑过只使用docker cp,但问题是我需要将应用程序杀死为新DLL中的cp,而K8S会自动重新启动它。
答案 0 :(得分:0)
我认为我发现了一些可行的方法。通过结合后两种解决方案(使A.hotbin.dll拦截所有解析失败,并让A.hotbin.dll在启动时加载/ local /中的所有dll),看来我至少能够启动该应用程序和运行。我将进行进一步测试,以确保它确实正常工作,如果是这种情况,请编辑此答案。
编辑:是的,看起来可行。供以后参考,这是我所拥有的:
/root/
|
+- A.dll
+- A.hotbin.dll
+-/local/
|
+-B.dll
+-C.dll
我执行A.hotbin.dll而不是A.dll。 A.hotbin.dll为AppDomain.CurrentDomain.AssemblyResolve
添加了一个解析失败的挂钩。该挂钩在/ local /文件夹中查找dll,如果找到,则将其返回。如果不是,则返回null(允许正常的dll解析继续)。然后,A.hotbin.dll进入本地文件夹,并遍历在其中找到的所有dll。对于每个dll,它将尝试通过AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(dllfilename))
将其加载到当前的AppDomain中。该调用将无法解析该dll,因此它将调用我的钩子,该钩子将找到它。加载所有dll之后,A.hotbin.dll Activator.CreateInstance-es A.dll并将控制权移交给他。