2012-01-02 4 views
3

私は第三者のライブラリを参照するプロジェクトを持っています。ライブラリの製造元は、定期的に新しいバージョンをリリースしています。私の最終的な目標は、実行時にどのバージョンを使用する必要があるかを実行時に選択できるようにすることです。実行時に強く署名されたアセンブリを交換します

現時点では、コンパイル時に使用されたバージョンよりも高いバージョンのアセンブリを実行時にロードしようとしています。プロジェクトをコンパイルし、第三者のライブラリを新しいバージョンに置き換え、アプリケーションを実行しようとします。これは私が問題になったことです。

を「位置アセンブリのマニフェスト定義はアセンブリ参照に一致しない」アセンブリが強く署名されているので、私は、このエラーが表示しsupprisedいませんでした:私はというエラーを取得します。私はこれを回避する方法を探しましたが、これまでのところ運がありません。

私はバインディングリダイレクトが私を助けてくれると思っていましたが、「新バージョン」の範囲を指定できないという欠点があります。どんな組み合わせでも動作し、古いバージョンでは古いバージョンで動作し、その逆もあります。

<bindingRedirect oldVersion="1.2.7.0" newVersion="1.2.8.0" /> 

http://msdn.microsoft.com/en-us/library/eftw1fys.aspx

私はまた、動的呼び出しを見てきましたが、その後、私は(私のコードは、広く第3回パーティのアセンブリで定義された型を使用しています)型の安全性を失います。 →参照を削除するのは困難です。

プロジェクト定義の参照で公開鍵を削除しても、それは役に立ちませんでした。コンパイル中に使用された他のアセンブリバージョンは失敗します。

<Reference Include="<assemblyname>"> 
    <SpecificVersion>False</SpecificVersion> 
    <HintPath>..\..\Dependencies\<manufacturer>\1.2.7.0\<assemblyname>.dll</HintPath> 
</Reference> 

注: 、実行時にアセンブリをロードおよびアンロードするためのロジックが既に存在しています。 第三者のライブラリで利用できるインターフェイスがありません

+2

Brrと一致します。これはDLL Hellを機能として要求しています。強力な命名とは関係がありませんが、[AssemblyVersion]の不一致のために例外が発生します。 bindingRedirectは実際には唯一の良い解決策です。互換性のあるアセンブリの[AssemblyFileVersion]だけをインクリメントするようにベンダーに納得させることができない限り、あなたは立ち往生していません。 [AssemblyVersion]をインクリメントすることは、「互換性がなく、試していない」ことを意味します。 –

+0

@HansPassant AssemblyVersionが実際にインクリメントされ、マニフェストの不一致が発生します。マニフェストの不一致は強く署名されたアセンブリでのみ発生すると言うのは間違いありませんか?あるいは、この問題は署名されていないアセンブリにも当てはまりますか? [Assembly Versioning](http://msdn.microsoft.com/en-us/library/51ket42z.aspx) – Nickolas

+0

いいえ、[AssemblyVersion]のみここで重要です。署名されていないアセンブリでも全く同じ方法で失敗します。 –

答えて

1

AppDomainのAssemblyResolveイベントを処理することで、この問題を解決することができます(おそらく回避策が役立ちます)。このイベントを処理すると、アセンブリを検出する通常の方法がすべて一致するバージョンを見つけられなかった場合に、ロードする必要があるアセンブリを提供する機会が与えられます。

ResolveEventArgs.Nameプロパティを確認して、アセンブリをロードする必要があるかどうかを確認する必要があります。 Nameプロパティは、ロードされるアセンブリのロングネーム(つまり、 'Widget.Net、Version = 1.2.3.4、Culture = neutral、PublicKeyToken = xxxxxxxxxxx')になります。

正しいロード要求が特定されたら、正しいバージョンのアセンブリ(Assembly.LoadFrom、Assembly.Load、Assembly.LoadWithPartialName)をロードし、イベントハンドラから戻します。 Assembly.LoadWithPartialNameは廃止とマークされていますが、ターゲットアセンブリがGACにある場合にこの問題を処理する唯一の方法と思われます。

これは問題を '解決しているが、どの意味でも良い解決策ではないことに注意することが重要です。 .Netフレームワークで使用されているアセンブリの通常のバージョンと厳密な名前のチェックを完全に覆します。これは、(質問のように)ベンダーがアセンブリのバージョン管理を乱してしまったため、他に選択肢がないときに行うことです。また、参照されたバージョンとロードされたバージョンの間でアセンブリで定義されたクラス(つまり、使用するすべてのクラス、プロパティ、メソッドなどが依然として存在し、同じシグネチャを持っている)に大きな変更がないことに頼っています。

セキュリティの少なくともふりを維持するためには、それは非常に良いアイデアだとに、AssemblyResolveイベントハンドラ内の少なくとも確認するには:

  1. 読み込まれたアセンブリのバージョンがバージョンが
  2. を要求されたよりも新しいですロードされ要求されたアセンブリの公開鍵トークンは、
関連する問題