Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
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 dynamische Assembly, die zum Speichern erstellt wird, wird persistierte Assembly genannt, während die reguläre Assembly, die nur im Speicher abgelegt wird, transient oder runnable genannt 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ührbare dynamische Assemblys in .NET
Verwenden Sie die AssemblyBuilder-Methode, um ein AssemblyBuilder.DefineDynamicAssembly-Runnable-Objekt abzurufen. Dynamische Assemblys können mit einem der folgenden Zugriffsmodi erstellt werden:
-
Die dynamische Assembly, die durch eine AssemblyBuilder repräsentiert wird, kann zum Ausführen des generierten Codes verwendet werden.
AssemblyBuilderAccess.RunAndCollect
Die dynamische Assembly, die durch ein AssemblyBuilder dargestellt wird, kann zum Ausführen des emittierten Codes verwendet werden und wird automatisch vom Garbage Collector zurückgewonnen.
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 }));
}
Persistierte dynamische Baugruppen in .NET
In .NET können Sie mit dem Typ PersistedAssemblyBuilder, der von AssemblyBuilder abgeleitet ist, dynamische Assemblys speichern. Weitere Informationen finden Sie in den Verwendungsszenarien und Beispielen bei 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 der Basisklasse Assembly, wie z. B. GetModules 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 GetModules auf dem geladenen Assembly Objekt auf. 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.
Mithilfe von KeyPair ist die Signierung einer dynamischen Assembly erst wirksam, wenn die Assembly auf dem Datenträger gespeichert wird. Starke Namen funktionieren also nicht mit transienten 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 Senden an Remote-Anwendungsdomänen
In einigen Szenarien muss eine dynamische Assembly erstellt und in einer Remoteanwendungsdomäne ausgeführt werden. Reflection emit bietet nicht die Möglichkeit, eine dynamische Assembly direkt in eine remote Domäne zu emittieren. Die Lösung besteht darin, die dynamische Assembly in der aktuellen Anwendungsdomäne auszustrahlen, die ausgegebene dynamische Assembly auf dem Datenträger zu speichern und dann die dynamische Assembly in die Remoteanwendungsdomäne zu laden. Die Remoting- und Anwendungsdomänen werden nur in .NET Framework unterstützt.