14

アセンブリの動的読み込みと、それらのアセンブリからのクラス インスタンスの作成に関する小さなコードを作成しました。これには、実行可能ファイル、動的に読み込まれるテスト ライブラリ、および動的アセンブリを新しい .xml ファイルに読み込むローダー ライブラリが含まれますAppdomain。ローダー ライブラリは、実行可能ライブラリと動的ライブラリの両方から参照されます。

//executable
[System.STAThreadAttribute()]
[System.LoaderOptimization(LoaderOptimization.MultiDomain)]
static void Main(string[] args)
{       
    AppDomainSetup domainSetup = new AppDomainSetup()
    {
        ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
        ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
        ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
        LoaderOptimization = LoaderOptimization.MultiDomain
    };
    AppDomain childDomain = AppDomain.CreateDomain("MyDomain", null, domainSetup);
    Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
    Console.WriteLine(childDomain.SetupInformation.LoaderOptimization.ToString());

    byte[] assembly = null;
    string assemblyName = "CSTestLib"; 

    using (FileStream fs = new FileStream(assemblyName+".dll",FileMode.Open))
    {
        byte[] byt = new byte[fs.Length];
        fs.Read(byt,0,(int)fs.Length);
        assembly = byt;          
    }

    object[] pararmeters = {assemblyName,assembly}; 
    string LoaderAssemblyName = typeof(AssemblyLoader).Assembly.FullName;
    string LoaderClassName = typeof(AssemblyLoader).FullName;
    AssemblyLoader assloader = (AssemblyLoader)childDomain.CreateInstanceAndUnwrap(LoaderAssemblyName,LoaderClassName , true, BindingFlags.CreateInstance, null, parameters, null, null);


    object obj = assloader.Load("CSTestLib.Class1");
    object obj2 = assloader.Load("CSTestLib.Class2");

    AppDomain.Unload(childDomain);

    Console.ReadKey();
}

//Dynamic Lib
using System;


namespace CSTestLib
{
    public class Class1 :MarshalByRefObject
    {
        public Class1() { }
    }



    public class Class2 : MarshalByRefObject
    {
        public Class2() { }
    }
}

//Loader Library


using System;

namespace LoaderLibrary
{
    public class AssemblyLoader : MarshalByRefObject
    {
        string assemblyName;
        public AssemblyLoader(string assName, byte[] ass)
        {
            assemblyName = assName;
            AppDomain.CurrentDomain.Load(ass);
            Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + " " + AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
        }

        public object Load(string className)
        {
            object ret = null;
            try
            {
                ret = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName, className);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return ret;
        }
    }
}
  1. ここで私は方法を設定LoaderOptimizationAttributeしましたが、それはなぜですか?main()AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString();NotSpecified

  2. との違いはMultiDomainMultiDomainHost私にはあまり明確ではありません。MultiDomainHostGACアセンブリのみですか?私の状況では、どちらがより適していますか?

  3. これによると

    JIT コンパイルされたコードは、Assembly クラスの LoadFrom メソッドを使用してロード元コンテキストに読み込まれたアセンブリ、またはバイト配列を指定する Load メソッドのオーバーロードを使用してイメージから読み込まれたアセンブリに対して共有することはできません。

では、アセンブリがドメイン中立にロードされているかどうかをどのように検出できますか? ドメインニュートラルにロードされていることをどのように保証できますか?

4

1 に答える 1

15

この属性は、アセンブリをNGenでプリコンパイルして、アプリケーションのウォーム スタートを高速化する場合にのみ効果があります。プリコンパイル済み (ngenned) アセンブリの使用を指定MultiDomainまたは有効にする場合。これは、ロードされたモジュールのリストを確認できるProcess ExplorerMultiDomainHostで確認できます。

アプリケーションがアセンブリを共有する複数の実行可能インスタンスで構成されている場合、これは起動時間を最大に節約する方法の 1 つです。これにより、.NET はプロセス間でコード ページを共有できるため、実際のメモリが節約され (1 つのアセンブリは物理メモリに 1 回だけ存在しますが、1 つまたは複数のプロセス間で共有されます)、各プロセスで同じコードを何度も JIT するのを防ぐことができます。これは、より動的なデータを使用して最も効率的なコードを生成できる通常の JIT でコンパイルした場合と同様に、生成されたコードの効率が少し低下するという犠牲を払って時間がかかります。

あなたの例では、マネージド ヒープにあるバイト配列にアセンブリを読み込み、プライベート バイト数を増やします。これにより、プロセス間でデータを共有できなくなります。プロセス間で共有できるのは、対応するページがハードディスク上にある読み取り専用ページのみです。これが、属性が効果を発揮しない理由です。ウォーム スタートアップのパフォーマンスが 2 倍になっている場合は、これが求めていた属性です。それ以外の場合は関係ありません。

元の質問に戻ります。

  1. 設定されていますが、デバッガーでアプリケーションを起動すると、このMultiDomain属性は無視されます。デバッガの外で起動すると、期待どおりの結果が得られます。
  2. はいMultiDomainHostは、署名されたアセンブリに対してのみ中立性を有効にAppDomainします。他のすべてのアセンブリは共有されません。
  3. コード共有は、プリコンパイルされている場合にのみ発生します。本当の問題は、アセンブリがプリコンパイルされているかどうかを確認する方法です。ロードされたモジュールのリストを見て、 Process Explorerでそれを行います。ロードされたアセンブリがネイティブ イメージ キャッシュへのパスと .ni 拡張子とともに表示された場合、プリコンパイルされたイメージが使用されていることは確かです。ランタイムでネイティブ イメージが使用されなかった理由を確認するためにラジオ ボタンを [ネイティブ イメージ] に設定すると、 fuslogvwでもこれを確認できます。
于 2011-04-25T21:17:55.210 に答える