Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用同一DLL的多个版本_C#_Visual Studio 2010_.net 4.0_Reference - Fatal编程技术网

C# 使用同一DLL的多个版本

C# 使用同一DLL的多个版本,c#,visual-studio-2010,.net-4.0,reference,C#,Visual Studio 2010,.net 4.0,Reference,我的任务是为应用程序创建一个新模块,因此,我将向项目中添加新的DLL。这一切都很好 然而,在我的DLL中,我想使用一个新版本的外部DLL(我无法控制)。如果我只是引用新的DLL并仅使用该DLL,我的代码将正常工作,但旧代码将停止工作 Could not load file or assembly 'itextsharp, Version=5.0.6.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca' or one of its depende

我的任务是为应用程序创建一个新模块,因此,我将向项目中添加新的DLL。这一切都很好

然而,在我的DLL中,我想使用一个新版本的外部DLL(我无法控制)。如果我只是引用新的DLL并仅使用该DLL,我的代码将正常工作,但旧代码将停止工作

Could not load file or assembly 'itextsharp, Version=5.0.6.0, Culture=neutral,
PublicKeyToken=8354ae6d2174ddca' or one of its dependencies. The located assembly's
manifest definition does not match the assembly reference. (Exception from HRESULT:
0x80131040)
我尝试了一个简单的方法来更改DLL的名称,但这显然有点太天真了,我认为它会起作用。我尝试过使用外部别名(通过在引用中定义它们),但我仍然不知道如何将两个同名文件放入一个BIN文件夹中

我该怎么办?你可以

可能太详细了,但这里有一篇文章演示了AppDomains在有用的设置中的使用及其工作原理:

从最基本的意义上讲,它可以归结为以下示例代码:

    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    ...

    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (/*some condition*/)
            return Assembly.LoadFrom("DifferentDllFolder\\differentVersion.dll");
        else
            return Assembly.LoadFrom("");
    }

您还可以依赖强名称程序集的程序集绑定重定向,如中所述


您将只有一个版本的文件(最新版本),并且两个引用都将解析为该文件。

另一个可行的选项是使用
extern
,如下所述:


如果AppDomains解决方案不适用于您的情况,您将面临时间压力,有相互冲突的需求(就像曾经发生过的那样),并且不介意可笑的人为攻击:

  • 使用该工具(Visual Studio附带的开发人员命令提示符的一部分)反编译程序集的较新版本
  • 编辑生成的.il文件以查找/替换程序集命名空间引用。使用引用的示例,这将是从itextsharp.X到itextsharp.new.X的更改
  • 同样,编辑AssemblyTitleAttribute的值。这需要将ASCII字符转换为十六进制
  • 使用以下命令重新编译.il文件
  • 请注意,对于任何从属组件(例如- 一些组件。核心。随便什么)
  • 使用不同的名称将新的.dll添加到项目中,并显式引用它们(而不是通过nuget或其他方式)

嘿,别那样看着我。我说的是荒谬的人工黑客…

让我们假设您有一个如下的项目结构:

…其中
A
B
是类库,
C
是可执行类型的项目(例如单元测试或控制台项目)

假设文件夹结构如下所示:

ABC.sln
A/A.csproj
A/...
B/B.csproj
B/...
C/C.csproj
C/...
lib/thirdparty4/thirdparty.dll
lib/thirdparty5/thirdparty.dll
C\bin\Debug\A.dll
C\bin\Debug\B.dll
C\bin\Debug\C.dll
C\bin\Debug\thirdparty4\thirdparty.dll
C\bin\Debug\thirdparty5\thirdparty.dll
如果我们试图简单地一起引用我们的项目,我们会遇到一个问题:两个版本的
thirdparty.dll
将被复制到同一个文件夹中(即
C
的输出(即bin)目录)。我们需要一种方法让
C
将两个DLL复制到它的输出目录中,并提供一种机制来引用其中一个

为了解决这个问题,我修改了
C.csproj
以包含以下内容:

<ItemGroup>
  <Content Include="..\lib\thirdparty4\thirdparty.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <Link>thirdparty4\thirdparty.dll</Link>
  </Content>
  <Content Include="..\lib\thirdparty5\thirdparty.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <Link>thirdparty5\thirdparty.dll</Link>
  </Content>
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="thirdparty" culture="neutral" publicKeyToken="1234567890123445"/>
        <bindingRedirect oldVersion="4.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
        <codeBase version="4.0.0.0" href="thirdparty4\thirdparty.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="thirdparty" culture="neutral" publicKeyToken="1234567890123445"/>
        <bindingRedirect oldVersion="5.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
        <codeBase version="5.0.0.0" href="thirdparty5\thirdparty.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
为了指示
C
使用这两个DLL,我在其中添加了一个
App.config
文件,如下所示:

<ItemGroup>
  <Content Include="..\lib\thirdparty4\thirdparty.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <Link>thirdparty4\thirdparty.dll</Link>
  </Content>
  <Content Include="..\lib\thirdparty5\thirdparty.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <Link>thirdparty5\thirdparty.dll</Link>
  </Content>
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="thirdparty" culture="neutral" publicKeyToken="1234567890123445"/>
        <bindingRedirect oldVersion="4.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
        <codeBase version="4.0.0.0" href="thirdparty4\thirdparty.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="thirdparty" culture="neutral" publicKeyToken="1234567890123445"/>
        <bindingRedirect oldVersion="5.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
        <codeBase version="5.0.0.0" href="thirdparty5\thirdparty.dll" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>


元素是可选的,但是如果您需要对其进行一系列修改,您可以使用它们。)

没有我希望的那么漂亮,但它完成了任务。谢谢我已经允许自己编辑您的答案,以包括我用来解决问题的代码示例。但主要原因是,第二个环节早已过时。你能把一个类似的资源链接到旧的吗?@Shaamaan我无法找到原始链接所指的内容:(这里有一个很好的入口页面,可以很好地替代:@Shaamaan。我想你的DLL依赖于其他DLL(版本不同)。因此,您添加了上述代码以解决此问题。对吗?在DLL的源代码中,您在何处/何时执行上述代码以挂接到ResolveEventHandler()。这应该发生在DLL初始化中,对吗?您是否使用了PreApplicationStartMethod()的方法?我无法获取PreApplicationStartMethod()方法有效。@Feru请记住这个问题是5年前提出来的,所以我现在对确切用例的记忆有点模糊。通常我正在开发的应用程序有“模块”(想想带大按钮的主屏幕)。我们的任务是创建一个新模块,因此我们决定将其作为一个单独的库保留。然后我们的库使用了一个从未有过的共享库版本(我认为它与PDF相关)。我认为解析代码在主应用程序中,但由于模块化的性质,我认为它可以连接到按钮按下。不要引用我的话,这是很久以前的事了。根据你的建议,可以在运行时选择加载哪个程序集?;我有3个不同的DLL,方法基本相同,等等,但是er工作是不同的,所以我希望能够选择一个版本并在整个过程中使用它。@coloboxp如果程序集在编译时已知并且可以全部引用,则可以使用
extern alias
和facades。很好的信息:如果程序集是trongly命名(例如,我有
Newtonsoft.Json.dll
Newtonsoft.Json.12.dll
)嗨,Jay,我的第三方dll是Microsoft.Azure.DocumentDB.Core.dll。我有相同的项目结构:项目A引用dll的v2.1.3(具有批量导入功能)和项目B引用v2.5.1(没有导入上限,但有一些其他功能)。我无法让你的东西正常工作,在项目A中调用方法时会出现“找不到方法”的情况。你有什么想法吗?谢谢。仅供参考:在旧ASP.NET Web表单项目的Web.Config中执行此操作时,我必须将标记上的href属性设置为“bin\thirdparty5\thirdparty.dll”用于查找dll。此操作无法修复运行时问题。链接已断开。