我们目前将 ODBC 驱动程序构建为 4 个 DLL:
实现 ODBC (C) API 的 DLL,主要用 C++ 实现, 一些用 C++/CLI 编写的“粘合”代码,用于与 #2、#3 和 #4 交互
包含托管程序集(用 C# 编写)的 DLL,它定义了用于 #1 和 #4 相互通信的“基本”接口(interface)。
- 另一个 DLL,包含依赖于 #2 的托管程序集,并定义了对 #2 中的类的一些扩展
- 另一个包含托管程序集的 DLL,其中包含“业务” 驱动程序的逻辑,取决于 #2 和 #3
为了部署驱动程序,我们将 DSN 配置为指向 #1,并将 #2、#3 和 #4 放入 GAC 中。
我们有一位客户希望完全避开 GAC。我知道将 #2、#3 和 #4 放入与加载 #1 的应用程序“有效”相同的目录中,但这不是一个好的解决方案,因为许多不同的应用程序可能会使用该驱动程序。
我们如何设置才能在没有 GAC 的情况下解决依赖关系?我尝试创建 list 文件(基于 https://learn.microsoft.com/en-us/windows/win32/sbscs/assembly-manifests ),但这似乎不起作用(抛出 EEFileLoadException 异常,因为它找不到托管程序集,一旦我从其中删除依赖项,就会发生同样的事情政府咨询委员会 (GAC))。我将 list 文件和所有 .DLL 放入同一目录中。
我通过一些(可能还不够)谷歌搜索找不到任何关于此案例的好的文档/示例。
最佳答案
我不确定我是否完全理解您的问题,但我会尽力回答:
在尝试解决这个问题时,我们应该记住以下几点:
- Fusion 不会启动(因此依赖项解析),直到您进入堆栈帧(未解析类型的第一次出现所在的位置)。
- 我们可以假设 CLR 已经加载到宿主进程中,并且我们至少有一个 Appdomain。 (否则,您必须考虑这两种情况 - 特别是被默认情况下不加载 CLR 的进程消耗。在这种情况下您想做什么?自己加载 CLR?隐式?显式?如果是这样,你如何配置你的Appdomain?你的App Root在哪里?你的探测路径是什么?)
鉴于这两点,您可以订阅AppDomain.AssemblyResolve Event 。但是您应该以这种方式重构您的代码,以便 fusion 在您成功订阅之前不会尝试解析您的程序集。在处理程序中,仅处理正在解析您的程序集的事件,并从您想要的任何位置加载它们 - 例如,从您的 native 库所在的同一路径。
补充阅读:
关于c++ - 如何在不使用 GAC 的情况下使 C++/CLI DLL 解析对托管程序集 (DLL) 的依赖关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58089153/