次の方法で共有


System.Reflection.Emit.AssemblyBuilder クラス

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

動的アセンブリは、リフレクション出力 API を使用して作成されるアセンブリです。 動的アセンブリは、別の動的アセンブリまたは静的アセンブリで定義されている型を参照できます。 AssemblyBuilderを使用すると、メモリ内に動的アセンブリを生成し、同じアプリケーションの実行中にコードを実行できます。 .NET 9 では、リフレクション出力のフル マネージド実装を備えた新しい PersistedAssemblyBuilder を追加しました。これにより、アセンブリをファイルに保存できます。 .NET Framework では、動的アセンブリを実行してファイルに保存する両方を実行できます。 保存用に作成された動的アセンブリは 永続化アセンブリ と呼ばれ、通常のメモリのみのアセンブリは 一時的 または 実行可能と呼ばれます。 .NET Framework では、動的アセンブリは 1 つ以上の動的モジュールで構成できます。 .NET Core と .NET 5 以降では、動的アセンブリは 1 つの動的モジュールのみで構成できます。

AssemblyBuilder インスタンスを作成する方法は実装ごとに異なりますが、モジュール、型、メソッド、または列挙型を定義する手順と IL を記述する手順は非常に似ています。

.NET での実行可能な動的アセンブリ

実行可能な AssemblyBuilder オブジェクトを取得するには、 AssemblyBuilder.DefineDynamicAssembly メソッドを使用します。 動的アセンブリは、次のいずれかのアクセス モードを使用して作成できます。

動的アセンブリが定義されていて、後で変更できない場合は、AssemblyBuilderAccess メソッドの呼び出しに適切なAssemblyBuilder.DefineDynamicAssembly値を指定して、アクセス モードを指定する必要があります。 ランタイムは、動的アセンブリのアクセス モードを使用して、アセンブリの内部表現を最適化します。

次の例では、アセンブリを作成して実行する方法を示します。

public void CreateAndRunAssembly(string assemblyPath)
{
    AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.Run);
    ModuleBuilder mob = ab.DefineDynamicModule("MyModule");
    TypeBuilder tb = mob.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
    MethodBuilder mb = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static,
                                                                   typeof(int), new Type[] {typeof(int), typeof(int)});
    ILGenerator il = mb.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Ldarg_1);
    il.Emit(OpCodes.Add);
    il.Emit(OpCodes.Ret);

    Type type = tb.CreateType();

    MethodInfo method = type.GetMethod("SumMethod");
    Console.WriteLine(method.Invoke(null, new object[] { 5, 10 }));
}

.NET での永続化された動的アセンブリ

PersistedAssemblyBuilderから派生した新しいAssemblyBuilder型。動的アセンブリを .NET Core に保存し、PersistedAssemblyBuilder ページの使用シナリオと例を確認できます。

.NET Framework での永続化された動的アセンブリ

.NET Framework では、動的アセンブリとモジュールをファイルに保存できます。 この機能をサポートするために、 AssemblyBuilderAccess 列挙体は、 SaveRunAndSaveの 2 つの追加フィールドを宣言します。

永続化可能な動的アセンブリ内の動的モジュールは、動的アセンブリが Save メソッドを使用して保存されるときに保存されます。 実行可能ファイルを生成するには、アセンブリのエントリ ポイントであるメソッドを識別するために、 SetEntryPoint メソッドを呼び出す必要があります。 SetEntryPoint メソッドがコンソール アプリケーションまたは Windows ベースのアプリケーションの生成を要求しない限り、アセンブリは既定で DLL として保存されます。

次の例では、.NET Framework を使用してアセンブリを作成、保存、および実行する方法を示します。

public void CreateRunAndSaveAssembly(string assemblyPath)
{
    AssemblyBuilder ab = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("MyAssembly"), AssemblyBuilderAccess.RunAndSave);
    ModuleBuilder mob = ab.DefineDynamicModule("MyAssembly.dll");
    TypeBuilder tb = mob.DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class);
    MethodBuilder meb = tb.DefineMethod("SumMethod", MethodAttributes.Public | MethodAttributes.Static,
                                                                   typeof(int), new Type[] {typeof(int), typeof(int)});
    ILGenerator il = meb.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Ldarg_1);
    il.Emit(OpCodes.Add);
    il.Emit(OpCodes.Ret);

    Type type = tb.CreateType();

    MethodInfo method = type.GetMethod("SumMethod");
    Console.WriteLine(method.Invoke(null, new object[] { 5, 10 }));
    ab.Save("MyAssembly.dll");
}

AssemblyGetModulesなど、基本GetLoadedModules クラスの一部のメソッドは、AssemblyBuilder オブジェクトから呼び出されると正しく動作しません。 定義された動的アセンブリを読み込み、読み込まれたアセンブリでメソッドを呼び出すことができます。 たとえば、返されたモジュールの一覧にリソース モジュールが含まれていることを確認するには、読み込まれたGetModules オブジェクトでAssemblyを呼び出します。 動的アセンブリに複数の動的モジュールが含まれている場合、アセンブリのマニフェスト ファイル名は、 DefineDynamicModule メソッドの最初の引数として指定されたモジュールの名前と一致する必要があります。

KeyPairを使用した動的アセンブリの署名は、アセンブリがディスクに保存されるまで有効ではありません。 そのため、厳密な名前は、一時的な動的アセンブリでは機能しません。

動的アセンブリは、別のアセンブリで定義されている型を参照できます。 一時的な動的アセンブリは、別の一時的な動的アセンブリ、永続化可能な動的アセンブリ、または静的アセンブリで定義されている型を安全に参照できます。 ただし、共通言語ランタイムでは、永続化可能な動的モジュールが、一時的な動的モジュールで定義されている型を参照することはできません。 これは、永続化された動的モジュールがディスクに保存された後に読み込まれると、ランタイムが一時的な動的モジュールで定義されている型への参照を解決できないためです。

リモート アプリケーション ドメインへの出力に関する制限事項

一部のシナリオでは、リモート アプリケーション ドメインで動的アセンブリを作成して実行する必要があります。 リフレクション出力では、動的アセンブリをリモート アプリケーション ドメインに直接出力することはできません。 解決策は、現在のアプリケーション ドメインで動的アセンブリを出力し、出力された動的アセンブリをディスクに保存してから、動的アセンブリをリモート アプリケーション ドメインに読み込みます。 リモート処理とアプリケーション ドメインは、.NET Framework でのみサポートされます。