c# - 如何同时使用 A.dll 和依赖于不同版本 A.dll 的第 3 方库
问题描述
我的应用程序和测试依赖于 .NET 供应商库和 System.Data.SQLite。供应商库也依赖于 System.Data.SQLite,但版本不同。我的申请包括:
- C# WinForm 应用程序
- 使用 C++/CLI 与供应商库交互的 C++ 应用程序
- 在 Visual Studio 中或通过自定义可执行文件运行的 C# 单元测试(在重复运行它们、更改测试设置等方面高度可配置)
使用 C# WinForm 应用程序修改 app.configdependentAssembly
非常简单。我们将旧的 SQLite DLL 放在一个子目录中,并使用以下命令重定向到它:
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" />
<codeBase version="1.0.98.0" href="SQLite_v1.0.98\System.Data.SQLite.dll" />
</dependentAssembly>
但我宁愿避免 C++ 应用程序的 .config 文件。尝试让 .config 文件为自定义测试运行程序可执行文件工作是一件非常痛苦的事情。因此,我尝试用在供应商库执行之前调用的预加载步骤替换 app.config 重定向:
public ref class AssemblyResolver
{
public:
static Reflection::Assembly^ ResolveEventHandler(Object^ sender, ResolveEventArgs^ args)
{
if (args->Name != "System.Data.SQLite, Version=1.0.98.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139")
return nullptr;
auto sb = gcnew Text::StringBuilder();
sb->Append(GetAssemblyDirectory());
sb->Append("\\SQLite_v1.0.98\\System.Data.SQLite.DLL");
return Reflection::Assembly::LoadFrom(sb->ToString());
}
//Returns the containing directory of the assembly that contains the function.
static String^ GetAssemblyDirectory()
{
auto codeBase = Reflection::Assembly::GetExecutingAssembly()->CodeBase;
auto uri = gcnew UriBuilder(codeBase);
auto path = Uri::UnescapeDataString(uri->Path);
return System::IO::Path::GetDirectoryName(path);
}
};
void preload()
{
AppDomain::CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler(AssemblyResolver::ResolveEventHandler);
}
这有效,除非应用程序在调用之前使用 SQLite 1.0.105 preload()
。我宁愿不必强制所有应用程序preload()
在启动应用程序时首先调用它们,所以我问是否有更好的方法。
例如,有没有一种简单的方法可以将供应商库(实际上是一组 DLL)放在具有旧 SQLite.dll 的子目录中,以便供应商 DLL 将使用该旧 SQLite,但所有其他第一方代码( DLL 和 EXE)将使用较新的 SQLite?同样,最好不需要 C++ 应用程序和单元测试运行器的 .config 文件。
更新:两个版本的 SQLite DLL 具有相同的名称。官方System.Data.SQLite.dll
。我有另一个供应商依赖项,我已经更新它以使用我们使用的相同 SQLite 版本(105)。根据@MickyD 的评论,我尝试将我们的 SQLite 文件更改为不同的名称:System.Data.SQLite.105.dll
. 但后来我得到一个错误:
无法加载文件或程序集 'System.Data.SQLite, Version=1.0.105.2, Culture=neutral, PublicKeyToken=db937bc2d44ff139' 或其依赖项之一。找到的程序集的清单定义与程序集引用不匹配。
由于这个其他供应商依赖项没有强命名,我可以反编译/重新编译它(事实上,我已经将它更新为 105)。所以我尝试更新名称以添加 .105 后缀:
.assembly extern System.Data.SQLite.105
{
.publickeytoken = (DB 93 7B C2 D4 4F F1 39 ) // ..{..O.9
.ver 1:0:105:2
}
这给了我一个错误重新编译:
将 'B.il' 组装到 DLL --> 'B.dll'
源文件是 ANSI
B.il(57):错误:标记“.105”处的语法错误:.assembly extern System.Data.SQLite.105
***** 失败 *****
每一次都被挫败!
解决方案
推荐阅读
- javascript - 在 ajax 表、jsp 和 servlet 中显示数据
- sql-server - 想要突出显示组中的每一行
- django - Django ORM:如何计算具有相同属性的对象?
- java - 如何将 Maven 添加到路径变量 windows 10?
- c - 如何用空格交换矩阵中的特定字符
- javascript - 在 Bootstrap 5.0 的选择菜单中搜索
- c# - 使用鼠标按钮在 X 和 Y 轴上围绕玩家对象旋转相机
- ios - 如何在 iOS 的应用程序目录中创建目录?
- docker - 为什么使用gosu时进程不与端口关联?
- python - Gitlab:通过 Python API 绑定获取项目的祖先组