Delen via


System.Reflection.Emit.AssemblyBuilder-klasse

In dit artikel vindt u aanvullende opmerkingen in de referentiedocumentatie voor deze API.

Een dynamische assembly is een assembly die wordt gemaakt met behulp van de Reflection Emit-API's. Een dynamische assembly kan verwijzen naar typen die zijn gedefinieerd in een andere dynamische of statische assembly. U kunt AssemblyBuilder dynamische assembly's genereren in het geheugen en de bijbehorende code uitvoeren tijdens dezelfde uitvoering van de toepassing. In .NET 9 hebben we een nieuwe PersistentedAssemblyBuilder toegevoegd met volledig beheerde implementatie van reflectie-emit waarmee u de assembly in een bestand kunt opslaan. In .NET Framework kunt u beide doen: voer de dynamische assembly uit en sla deze op in een bestand. De dynamische assembly die is gemaakt om op te slaan, wordt een persistente assembly genoemd, terwijl de normale assembly met alleen geheugen tijdelijke of uitvoerbare assembly wordt genoemd. In .NET Framework kan een dynamische assembly bestaan uit een of meer dynamische modules. In .NET Core en .NET 5+ kan een dynamische assembly slechts bestaan uit één dynamische module.

De manier waarop u een AssemblyBuilder exemplaar maakt, verschilt voor elke implementatie, maar verdere stappen voor het definiëren van een module, type, methode of enum, en voor het schrijven van IL, zijn vrij vergelijkbaar.

Uitvoerbare dynamische assembly's in .NET

Gebruik de methode om een runnable AssemblyBuilder object op te AssemblyBuilder.DefineDynamicAssembly halen. Dynamische assembly's kunnen worden gemaakt met een van de volgende toegangsmodi:

De toegangsmodus moet worden opgegeven door de juiste AssemblyBuilderAccess waarde in de aanroep van de AssemblyBuilder.DefineDynamicAssembly methode op te geven wanneer de dynamische assembly is gedefinieerd en later niet kan worden gewijzigd. De runtime gebruikt de toegangsmodus van een dynamische assembly om de interne weergave van de assembly te optimaliseren.

In het volgende voorbeeld ziet u hoe u een assembly maakt en uitvoert:

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

Persistente dynamische assembly's in .NET

Het nieuwe PersistedAssemblyBuilder type dat is afgeleid van de AssemblyBuilder en maakt het mogelijk om de dynamische assembly's in .NET Core op te slaan, de gebruiksscenario's en voorbeelden van de pagina PersistentedAssemblyBuilder te controleren.

Persistente dynamische assembly's in .NET Framework

In .NET Framework kunnen dynamische assembly's en modules worden opgeslagen in bestanden. Ter ondersteuning van deze functie declareert de AssemblyBuilderAccess opsomming twee extra velden: Save en RunAndSave.

De dynamische modules in de persistente dynamische assembly worden opgeslagen wanneer de dynamische assembly wordt opgeslagen met behulp van de Save methode. Als u een uitvoerbaar bestand wilt genereren, moet de SetEntryPoint methode worden aangeroepen om de methode te identificeren die het toegangspunt voor de assembly is. Assembly's worden standaard opgeslagen als DLL's, tenzij de SetEntryPoint methode het genereren van een consoletoepassing of een Windows-toepassing aanvraagt.

In het volgende voorbeeld ziet u hoe u een assembly maakt, opslaat en uitvoert met behulp van .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");
}

Sommige methoden op de basisklasse Assembly , zoals GetModules en GetLoadedModules, werken niet correct wanneer ze worden aangeroepen vanuit AssemblyBuilder objecten. U kunt de gedefinieerde dynamische assembly laden en de methoden voor de geladen assembly aanroepen. Als u er bijvoorbeeld voor wilt zorgen dat resourcemodules zijn opgenomen in de lijst met geretourneerde modules, roept GetModules u het geladen Assembly object aan. Als een dynamische assembly meer dan één dynamische module bevat, moet de naam van het manifestbestand van de assembly overeenkomen met de naam van de module die is opgegeven als het eerste argument voor de DefineDynamicModule methode.

Het ondertekenen van een dynamische assembly die wordt gebruikt KeyPair , is pas van kracht als de assembly op de schijf is opgeslagen. Sterke namen werken dus niet met tijdelijke dynamische assembly's.

Dynamische assembly's kunnen verwijzen naar typen die zijn gedefinieerd in een andere assembly. Een tijdelijke dynamische assembly kan veilig verwijzen naar typen die zijn gedefinieerd in een andere tijdelijke dynamische assembly, een persistente dynamische assembly of een statische assembly. Met de common language Runtime kan echter geen persistente dynamische module verwijzen naar een type dat is gedefinieerd in een tijdelijke dynamische module. Dit komt doordat wanneer de persistente dynamische module wordt geladen nadat deze op de schijf is opgeslagen, de runtime de verwijzingen naar typen die zijn gedefinieerd in de tijdelijke dynamische module, niet kan worden omgezet.

Beperkingen voor verzenden naar externe toepassingsdomeinen

Voor sommige scenario's moet een dynamische assembly worden gemaakt en uitgevoerd in een extern toepassingsdomein. Reflectie-emit staat niet toe dat een dynamische assembly rechtstreeks naar een extern toepassingsdomein wordt verzonden. De oplossing is het verzenden van de dynamische assembly in het huidige toepassingsdomein, het opslaan van de verzonden dynamische assembly op schijf en vervolgens de dynamische assembly laden in het domein van de externe toepassing. De externe toegang en toepassingsdomeinen worden alleen ondersteund in .NET Framework.