如何同时使用A.dll和依赖于其他版本的A.dll的第三方库

时间:2018-06-28 14:35:06

标签: c# .net .net-assembly

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

  • C#WinForm应用程序
  • 使用C ++ / CLI与供应商库接口的C ++应用程序
  • 在Visual Studio或自定义可执行文件中运行的C#单元测试(关于重复运行它们,更改测试设置等,可以高度配置)

使用dependentAssembly修改C#WinForm应用程序的app.config很容易。我们将较旧的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);
}

除了在调用preload()之前应用程序使用SQLite 1.0.105的情况下,此方法有效。我宁愿不必强制所有应用程序在启动应用程序时首先调用preload(),所以我问是否有更好的方法。

例如,有一种简单的方法可以将供应商库(实际上是一组DLL)放入带有较旧的SQLite.dll的子目录中,以便供应商DLL将使用该较旧的SQLite,但所有其他的1st方代码(DLL和EXE)将使用较新的SQLite?同样,最好不需要C ++应用程序和单元测试运行程序的.config文件。

更新: 两个版本的SQLite DLL具有相同的名称。官方System.Data.SQLite.dll。我还有另一个供应商依赖性,我已经更新为使用与我们使用的相同的SQLite版本(105)。基于@MickyD的评论,我尝试将SQLite文件更改为其他名称:System.Data.SQLite.105.dll。但是然后我得到了一个错误:

  

无法加载文件或程序集'System.Data.SQLite,   版本= 1.0.105.2,文化=中性,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):错误:.assembly extern中标记“ .105”处的语法错误   System.Data.SQLite.105

     

*****故障*****

动oil动静!

0 个答案:

没有答案