私たちのアプリケーションはかなり最近の protobuf-net (バージョン 2.0.0.668) を使用しており、古いバージョンの protobuf-net (バージョン 1.0.0.282) を使用するクライアント ライブラリを持つ別のシステムに統合しようとしています。同じ Windows サービスでアセンブリ リゾルバーを使用してライブラリを並べて使用することは可能ですか? シリアライザーに関して、これらのバージョン間に重大な変更があること、およびバージョン間に個別の protobuf プロトコルの重大な変更があることを理解しています。
アセンブリ リゾルバー アプローチを使用しようとしたのは、アウト オブ プロセスに移行し、クライアント呼び出しごとに回線経由で呼び出しを行うことで、このクライアント ライブラリの呼び出しのオーバーヘッドを削減したかったからです。私はそれを並行して機能させたかったのです。
アセンブリ リゾルバーが配置されている場合でも (詳細は後述)。そして、新しいバージョンを取得するように見える古いprotobufを必要とするライブラリでAssembly.Loadを呼び出します。バインドされたリダイレクトがない場合でも。また、バインディング リダイレクトの自動生成を無効にするようにプロジェクト ファイルで具体的に指定しました。
バージョン 1.0.0.282 を使用するようにプロジェクトへの特定のバージョン参照を指定した場合でも、完全に分離されたプロジェクトが新しいバージョンの protobuf にデフォルト設定されるのはなぜですか? 最終結果は、protobuf.net のバージョン 1.0.0.282 バージョンを必要とするライブラリで protobuf メッセージを正常にシリアル化できないということです。
GAC を使用しないという制約があり、別のサービスで古いバージョンのクライアント ライブラリへの呼び出しをラップする別のサービスを作成しないという制約があり、プロセス外になることで非常に高価な呼び出しになります。
私のプロジェクト構造は次のとおりです
ソリューション |_WindowsService - DLL LibraryA および DLLLibraryB を参照 |_DLL_LibraryA - protobuf 2.0.0.668 および DLL_LibraryB を参照 |_DLL_LibraryB - protobuf 1.0.0.282 および DLL_ThirdpartyClient を参照
DLL_LibraryA および DLL_LibraryB プロジェクトは、特定のバージョンを使用し、ローカルにコピーしないように、protobuf.net への参照を使用してセットアップされます。
WindowsService プロジェクトでビルド イベントを作成し、appdomain resolveassembly イベントがトリガーされたときにアセンブリ ローダーによって検出されるように、bin->ThirdParty->protobuf-net->{version} フォルダー内の protobuf-net ファイルをファイル コピーしました。
アセンブリを完全に分離し、プロジェクト構成を設定してバインディング リダイレクトの自動生成を無効にしても (自動バインディング リダイレクトを無効にする)。私のアセンブリ ローダーは、バージョン 2.0.0.668 に対してのみ呼び出されます。
ただし、興味深い点の 1 つは、私たちのソリューションが合成と依存性注入に MEF を利用していることです。効果があるのかしらん。また、私のソリューションの構造に基づいて、DLL_LibraryA は protobuf-net 2.0.0.668 に依存し、間接的に DLL_LibraryB の依存関係を介して protobuf-net 1.0.0.282 に依存します。この場合、clr は何をしますか? プロセスから外れることなくこれを成功させる方法はありますか? CLR が常に最新バージョンをロードすることを決定したのは、依存関係が混在しているためですか?
どんな情報でも大歓迎です。
詳細はこちら:
バージョン リゾルバーを作成する - アセンブリ リゾルバーを使用する Side-by-Side アセンブリを使用して x64 または x32 バージョンの DLL をロードする
public static Assembly VersionResolver(object sender, ResolveEventArgs args){ var assemblyName = new AssemblyName(args.Name); var name = assemblyName.Name; var version = assemblyName.Version.ToString(); string versionedAssemblyProbingPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, string.Format(@"{0}\{1}\{2}", THIRD_PARTY_FOLDER, name, version), string.Format("{0}.dll", name));Assembly returnAssembly = null; if (File.Exists(versionedAssemblyProbingPath)) { returnAssembly = Assembly.LoadFile(versionedAssemblyProbingPath); } else { //Log here and return null } return returnAssembly; }
Windows サービス プログラムでリゾルバーを呼び出す -
static Program() { AppDomain.CurrentDomain.AssemblyResolve += VersionResolver; }