【问题标题】:Same DLLs two different versions相同的 DLL 两个不同的版本
【发布时间】:2019-09-18 14:02:52
【问题描述】:

我有两个不同的项目,都使用来自 NuGet 的 Newtonsoft.Json。

  • 项目 A 使用 9.0.1 版本。
  • 项目 B 使用版本 11.0.1。

在构建项目时,一个 dll 会覆盖另一个 dll,因为它们都在同一个文件夹中编译。

如何重定向单独文件中 dll 的编译,如何说项目 A 使用 9.0.1 而项目 B 使用 11.0.1?

最好有一个文件夹“Newtonsoft”,并且有两个文件夹“11”和“9”。在这些文件夹中是特定版本。 (如果有其他解决方案,那么我也可以接受另一个解决方案。

项目 A 和项目 B 都是“插件”,我的应用程序正在使用它们,其中包括来自插件文件夹的那些插件。这意味着我目前有一个使用以下 dll 的应用程序(它们是都在一个文件夹中):

  • Project_A.dll
  • Project_B.dll
  • NewtonSoft.Json.dll(9.0.1 或 11.0.1)

ProjectA.dll

这是我的 app.config

项目A:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="YamlDotNet" publicKeyToken="ec19458f3c15af5e" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

项目 B:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
        <codeBase version="11.0.0.1" href="Newtonsoft.Json.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /></startup></configuration>

【问题讨论】:

  • 您是否考虑过将两个项目更改为使用相同的版本?
  • @mjwills 我有,但是项目 B 使用了一些功能,这些功能仅在 11.0.1 中可用。在项目 A 中,我使用了另一个 Nuget 包,它仅适用于 9.0.1。因此我需要两个 dll,因为我无法升级/降级版本。
  • bindingRedirect 必须应用于使用这些 DLL 的项目。所以你的 EXE 项目,而不是库项目。
  • 答案属于 answers,未编辑到问题中。如果您有答案,请将其作为一个发布并(在冷却期之后)接受它。

标签: c# dll nuget


【解决方案1】:

您可以将程序集放在不同的文件夹中(不一定直接放在 bin 文件夹中)并使用 codeBase 元素:

<configuration>
<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="Some.API" publicKeyToken="12ab3cd4e5f6abcd"
              culture="neutral" />
            <codeBase version="1.0.0.0" href="v1\Some.API.dll" />
            <codeBase version="2.0.0.0" href="v2\Some.API.dll" />
            <!-- INFO: The version attribute represents an assembly 
                       version which doesn't always have to match the 
                       NuGet package version.
                       The codebase attribute can be anywhere on 
                       the local intranet or the Internet. -->
        </dependentAssembly>
    </assemblyBinding>
</runtime>

来源:https://devnet.kentico.com/articles/referencing-multiple-versions-of-the-same-assembly-in-a-single-application

【讨论】:

  • 我明天试试 :)
【解决方案2】:

已解决

通过这样做让它工作:

在我使用 Newtonsfot.Json 的任何方法/类之前,我使用以下两行:

//The AssemblyResolve event is called when the common language runtime tries to bind to the assembly and fails.
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);

如果应用程序抛出异常,将始终调用该事件

无法加载文件或程序集 'Newtonsoft.Json, Version=9.0.0.1, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' 或其之一 依赖关系。系统找不到指定的文件。

因此事件会捕获事件并加载正确的 dll:

Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    //This handler is called only when the common language runtime tries to bind to the assembly and fails.

    //Retrieve the list of referenced assemblies in an array of AssemblyName.
    Assembly MyAssembly, objExecutingAssemblies;
    string strTempAssmbPath = "";

    objExecutingAssemblies = Assembly.GetExecutingAssembly();
    AssemblyName[] arrReferencedAssmbNames = objExecutingAssemblies.GetReferencedAssemblies();

    //Loop through the array of referenced assembly names.
    foreach (AssemblyName strAssmbName in arrReferencedAssmbNames)
    {
        //Check for the assembly names that have raised the "AssemblyResolve" event.
        if (strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(",")) == args.Name.Substring(0, args.Name.IndexOf(",")))
        {
            //Build the path of the assembly from where it has to be loaded.
            //The following line is probably the only line of code in this method you may need to modify:
            strTempAssmbPath = "C:\\Program Files\\PATH TO YOUR FOLDER" + "\\Newtonsoft.Json\\9.0.1";
            if (!strTempAssmbPath.EndsWith("\\")) strTempAssmbPath += "\\";
            //strTempAssmbPath += args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll";
            strTempAssmbPath += strAssmbName.Name + ".dll";
            break;
        }

    }
    //Load the assembly from the specified path.
    MyAssembly = Assembly.LoadFrom(strTempAssmbPath);

    //Return the loaded assembly.
    return MyAssembly;
}

致谢:https://www.chilkatsoft.com/p/p_502.asp

【讨论】:

    猜你喜欢
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多