Freigeben über


System.Reflection.Emit.AssemblyBuilder-Klasse

Dieser Artikel enthält ergänzende Hinweise zur Referenzdokumentation für diese API.

Eine dynamische Assembly ist eine Assembly, die mithilfe der Reflection Emit-APIs erstellt wird. Eine dynamische Assembly kann auf Typen verweisen, die in einer anderen dynamischen oder statischen Assembly definiert sind. Sie können AssemblyBuilder verwenden, um dynamische Assemblys im Arbeitsspeicher zu generieren und deren Code während der gleichen Anwendungsausführung auszuführen. In .NET 9 haben wir eine neue PersistedAssemblyBuilder mit vollständig verwalteter Implementierung von Spiegelungs-Emit hinzugefügt, mit der Sie die Assembly in einer Datei speichern können. In .NET Framework können Sie beides ausführen– führen Sie die dynamische Assembly aus, und speichern Sie sie in einer Datei. Die für das Speichern erstellte dynamische Assembly wird als permanente Assembly bezeichnet, während die normale Nur-Speicherassembly als vorübergehend oder runnierbar bezeichnet wird. In .NET Framework kann eine dynamische Assembly aus einem oder mehreren dynamischen Modulen bestehen. In .NET Core und .NET 5+ kann eine dynamische Assembly nur aus einem dynamischen Modul bestehen.

Die Art und Weise, wie Sie eine AssemblyBuilder Instanz erstellen, unterscheidet sich für jede Implementierung, aber weitere Schritte zum Definieren eines Moduls, typs, einer Methode oder einer Enumeration sowie zum Schreiben von IL sind ziemlich ähnlich.

Ausführen von dynamischen Assemblys in .NET

Verwenden Sie die AssemblyBuilder.DefineDynamicAssembly Methode, um ein runnable-Objekt AssemblyBuilder abzurufen. Dynamische Assemblys können mit einem der folgenden Zugriffsmodi erstellt werden:

Der Zugriffsmodus muss angegeben werden, indem der entsprechende AssemblyBuilderAccess Wert im Aufruf der AssemblyBuilder.DefineDynamicAssembly Methode angegeben wird, wenn die dynamische Assembly definiert ist und später nicht geändert werden kann. Die Laufzeit verwendet den Zugriffsmodus einer dynamischen Assembly, um die interne Darstellung der Assembly zu optimieren.

Im folgenden Beispiel wird das Erstellen und Ausführen einer Assembly veranschaulicht:

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 }));
}

Beibehaltene dynamische Assemblys in .NET

Der neue PersistedAssemblyBuilder Typ, der von den AssemblyBuilder dynamischen Assemblys in .NET Core abgeleitet wurde, ermöglicht das Speichern der dynamischen Assemblys, überprüfen Sie die Verwendungsszenarien und Beispiele auf der Seite "PersistedAssemblyBuilder ".

Beibehaltene dynamische Assemblys in .NET Framework

In .NET Framework können dynamische Assemblys und Module in Dateien gespeichert werden. Zur Unterstützung dieses Features deklariert die AssemblyBuilderAccess Enumeration zwei zusätzliche Felder: Save und RunAndSave.

Die dynamischen Module in der dauerhaften dynamischen Assembly werden gespeichert, wenn die dynamische Assembly mithilfe der Save Methode gespeichert wird. Zum Generieren einer ausführbaren Datei muss die SetEntryPoint Methode aufgerufen werden, um die Methode zu identifizieren, die der Einstiegspunkt für die Assembly ist. Assemblys werden standardmäßig als DLLs gespeichert, es sei denn, die SetEntryPoint Methode fordert die Generierung einer Konsolenanwendung oder einer Windows-basierten Anwendung an.

Im folgenden Beispiel wird das Erstellen, Speichern und Ausführen einer Assembly mithilfe von .NET Framework veranschaulicht.

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");
}

Einige Methoden für die Basisklasse Assembly , z GetModules . B. und GetLoadedModules, funktionieren nicht ordnungsgemäß, wenn sie von AssemblyBuilder Objekten aufgerufen werden. Sie können die definierte dynamische Assembly laden und die Methoden für die geladene Assembly aufrufen. Um beispielsweise sicherzustellen, dass Ressourcenmodule in der zurückgegebenen Modulliste enthalten sind, rufen Sie das geladene Assembly Objekt aufGetModules. Wenn eine dynamische Assembly mehrere dynamische Module enthält, sollte der Manifestdateiname der Assembly mit dem Namen des Moduls übereinstimmen, der als erstes Argument der DefineDynamicModule Methode angegeben ist.

Die Signierung einer dynamischen Assembly mithilfe KeyPair einer dynamischen Assembly ist erst wirksam, wenn die Assembly auf dem Datenträger gespeichert wird. Daher funktionieren starke Namen nicht mit vorübergehenden dynamischen Assemblys.

Dynamische Assemblys können auf typen verweisen, die in einer anderen Assembly definiert sind. Eine vorübergehende dynamische Assembly kann sicher auf Typen verweisen, die in einer anderen vorübergehenden dynamischen Assembly, einer persistierbaren dynamischen Assembly oder einer statischen Assembly definiert sind. Die Common Language Runtime lässt jedoch nicht zu, dass ein persistentes dynamisches Modul auf einen Typ verweist, der in einem vorübergehenden dynamischen Modul definiert ist. Dies liegt daran, dass beim Laden des beibehaltenen dynamischen Moduls nach dem Speichern auf dem Datenträger die Verweise auf Typen, die im vorübergehenden dynamischen Modul definiert sind, nicht aufgelöst werden können.

Einschränkungen beim Ausstellen von Remoteanwendungen Standard

In einigen Szenarien muss eine dynamische Assembly erstellt und in einer Remoteanwendung ausgeführt werden Standard. Spiegelungsausstoß lässt nicht zu, dass eine dynamische Assembly direkt an eine Remoteanwendung ausgegeben wird Standard. Die Lösung besteht darin, die dynamische Assembly in der aktuellen Anwendung zu senden Standard, die ausgegebene dynamische Assembly auf dem Datenträger zu speichern und dann die dynamische Assembly in die Remoteanwendung zu laden Standard. Das Remoting und die Anwendung werden nur in .NET Framework unterstützt Standard.