web-dev-qa-db-ja.com

同じ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の名前を変更する簡単な方法を試してみましたが、どうやらそれがうまくいくとは思えないほど、私にはあまりにも素朴すぎました。 (参照で定義することにより)外部エイリアスを使用しようとしましたが、同じ名前の2つのファイルを1つのBINフォルダーに取得する方法がわかりません...

私は何をすべきか?

29
Shaamaan

特定のAppDomainに別のバージョンをロードする

おそらく詳細すぎるかもしれませんが、有用な設定でAppDomainを使用する方法とその機能を説明する記事を次に示します。

http://msdn.Microsoft.com/en-us/magazine/cc164072.aspx

非常に基本的な意味では、次のサンプルコードになります。

    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("");
    }
17
sehe

次のようなプロジェクト構造があるとします。

Project Diagram

...ここで、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

プロジェクトを一緒に単純に参照しようとすると、問題が発生します。thirdparty.dllの2つのバージョンが、同じフォルダー(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>

これにより、出力ディレクトリにthirdparty4\thirdparty.dllthirdparty5\thirdparty.dllの両方を作成するように指示されます。

Cをビルドすると、その出力ディレクトリは次のようになります。

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

これらのdllの両方を使用するようにCに指示するために、App.configファイルを次のように追加しました。

<?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>

これにより、必要なバージョンに応じて、いずれかのDLLまたはもう一方を使用します。どちらも出力ディレクトリのサブフォルダー内で使用できます。( bindingRedirect 要素はオプションですが、これを適用するために一連のリビジョンが必要な場合は使用できます。)

12
Jay Sullivan

ここで説明するように、もう1つの実行可能なオプションはexternを使用することです。

http://blogs.msdn.com/b/abhinaba/archive/2005/11/30/498278.aspx

5
fozylet

AppDomainsソリューションが該当しない場合は、時間のプレッシャーにさらされており、が発生するなどの競合する要件があり、ばかげて考案されたハッキン​​グを気にしないでください。

  • ildasm ツールを使用して、アセンブリの新しいバージョンを逆コンパイルします(Visual Studioに含まれている開発者コマンドプロンプトの一部)
  • 生成された.ilファイルを編集して、アセンブリ名前空間参照を検索/置換します。引用された例を使用すると、これはitextsharp.Xからitextsharp.new.Xへの変更になります。
  • 同様に、AssemblyTitleAttributeの値を編集します。 ASCII文字を16進数に変換する必要があります。
  • ilasm を使用して.ilファイルを再コンパイルします
  • これは、依存するアセンブリ(たとえば-someassembly.core.whatever)に対して繰り返す必要がある場合があることに注意してください。
  • 新しい.dllをプロジェクトに別の名前で追加し、(nugetなどではなく)明示的に参照する

ねえ、そんなふうに見ないで。 ばかばかしく工夫されたハック...

3
Vecht

http://msdn.Microsoft.com/en-us/library/2fc472t2.aspx で説明されているように、厳密な名前のアセンブリのアセンブリバインディングリダイレクトに依存することもできます。

ファイルのバージョンは1つ(最新)だけで、両方の参照で解決されます。

1
fsimonazzi