3

私たちのアプリケーションはかなり最近の 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 が常に最新バージョンをロードすることを決定したのは、依存関係が混在しているためですか?

どんな情報でも大歓迎です。

詳細はこちら:

  1. バージョン リゾルバーを作成する - アセンブリ リゾルバーを使用する 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;
    }
    
  2. Windows サービス プログラムでリゾルバーを呼び出す -

    static Program() { AppDomain.CurrentDomain.AssemblyResolve += VersionResolver; }

4

0 に答える 0