首页 > 解决方案 > 如何同时使用 A.dll 和依赖于不同版本 A.dll 的第 3 方库

问题描述

我的应用程序和测试依赖于 .NET 供应商库和 System.Data.SQLite。供应商库也依赖于 System.Data.SQLite,但版本不同。我的申请包括:

使用 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

***** 失败 *****

每一次都被挫败!

标签: c#.net.net-assembly

解决方案


推荐阅读