次の方法で共有


System.Runtime.Loader.AssemblyLoadContext クラス

この記事では、この API のリファレンス ドキュメントに補足的な解説を提供します。

AssemblyLoadContextは、読み込みコンテキストを表します。 概念的には、読み込みコンテキストによって、一連のアセンブリの読み込み、解決、およびアンロードのスコープが作成されます。

AssemblyLoadContextは、主にアセンブリの読み込み分離を提供するために存在します。 これにより、同じアセンブリの複数のバージョンを 1 つのプロセス内に読み込むことができます。 .NET Framework の複数の AppDomain インスタンスによって提供される分離メカニズムが置き換えられます。

  • AssemblyLoadContext では、セキュリティ機能は提供されません。 すべてのコードには、プロセスの完全なアクセス許可があります。
  • .NET Core 2.0 - 2.2 でのみ、 AssemblyLoadContext は抽象クラスです。 これらのバージョンで具象クラスを作成するには、 AssemblyLoadContext.Load(AssemblyName) メソッドを実装します。

ランタイムでの使用方法

ランタイムは、次の 2 つのアセンブリ読み込みコンテキストを実装します。

  • AssemblyLoadContext.Default はランタイムの既定のコンテキストを表します。これは、アプリケーションのメイン アセンブリとその静的な依存関係に使用されます。
  • Assembly.LoadFile(String) メソッドは、最も基本的なAssemblyLoadContextをインスタンス化することによって、読み込むアセンブリを分離します。 依存関係の解決なしで各アセンブリを独自の AssemblyLoadContext に読み込む単純な分離スキームがあります。

アプリケーションの使用状況

アプリケーションは、独自の AssemblyLoadContext を作成して、高度なシナリオ用のカスタム ソリューションを作成できます。 このカスタマイズでは、依存関係解決メカニズムの定義に重点を置いています。

AssemblyLoadContextには、マネージド アセンブリ解決を実装するための 2 つの拡張ポイントが用意されています。

  1. AssemblyLoadContext.Load(AssemblyName) メソッドは、AssemblyLoadContextがアセンブリを解決、読み込み、および返す最初の機会を提供します。 AssemblyLoadContext.Load(AssemblyName) メソッドがnullを返す場合、ローダーはアセンブリをAssemblyLoadContext.Defaultに読み込もうとします。
  2. AssemblyLoadContext.Defaultがアセンブリを解決できない場合、元のAssemblyLoadContextはアセンブリを解決する 2 回目の機会を得ます。 ランタイムは、 Resolving イベントを発生させます。

さらに、 AssemblyLoadContext.LoadUnmanagedDll(String) 仮想メソッドを使用すると、既定のアンマネージド アセンブリ解決をカスタマイズできます。 既定の実装は nullを返します。これにより、ランタイム検索で既定の検索ポリシーが使用されます。 ほとんどのシナリオでは、既定の検索ポリシーで十分です。

技術的な課題

  • 1 つのプロセスで複数のバージョンのランタイムを読み込むことはできません。

    注意事項

    複数のコピーまたは異なるバージョンのフレームワーク アセンブリを読み込むと、予期しない、診断が困難な動作につながる可能性があります。

    ヒント

    この分離の問題を解決するには、リモート処理またはプロセス間通信でプロセス境界を使用します。

  • アセンブリの読み込みのタイミングにより、テストとデバッグが困難になる可能性があります。 通常、アセンブリは、依存関係が直ちに解決されずに読み込まれます。 依存関係は、必要に応じて読み込まれます。

    • コードが依存アセンブリに分岐する場合。
    • コードがリソースを読み込む場合。
    • コードがアセンブリを明示的に読み込む場合。
  • AssemblyLoadContext.Load(AssemblyName)の実装では、異なるバージョンを存在させるために分離する必要がある新しい依存関係を追加できます。 最も自然な実装では、これらの依存関係が既定のコンテキストに配置されます。 慎重な設計により、新しい依存関係を分離できます。

  • 同じアセンブリが異なるコンテキストに複数回読み込まれます。

    • これにより、"'Sample.Plugin' 型のオブジェクトを 'Sample.Plugin' 型にキャストできません" などのエラー メッセージが混乱する可能性があります。
    • 分離境界を越えたマーシャリングは簡単ではありません。 一般的な解決策は、既定の読み込みコンテキストにのみ読み込まれるアセンブリで定義されたインターフェイスを使用することです。