System.Reflection.Emit.AssemblyBuilder-klass
Den här artikeln innehåller ytterligare kommentarer till referensdokumentationen för det här API:et.
En dynamisk sammansättning är en sammansättning som skapas med api:erna Reflection Emit. En dynamisk sammansättning kan referera till typer som definierats i en annan dynamisk eller statisk sammansättning. Du kan använda AssemblyBuilder för att generera dynamiska sammansättningar i minnet och köra deras kod under samma programkörning. I .NET 9 har vi lagt till en ny PersistedAssemblyBuilder med fullständigt hanterad implementering av reflektionsemitten som gör att du kan spara sammansättningen i en fil. I .NET Framework kan du göra båda – köra den dynamiska sammansättningen och spara den i en fil. Den dynamiska sammansättningen som skapas för att spara kallas för en bevarad sammansättning, medan den vanliga sammansättningen endast minne kallas för tillfällig eller körbar. I .NET Framework kan en dynamisk sammansättning bestå av en eller flera dynamiska moduler. I .NET Core och .NET 5+ kan en dynamisk sammansättning bara bestå av en dynamisk modul.
Hur du skapar en AssemblyBuilder instans skiljer sig åt för varje implementering, men ytterligare steg för att definiera en modul, typ, metod eller uppräkning och för att skriva IL är ganska lika.
Körbara dynamiska sammansättningar i .NET
Om du vill hämta ett runnable-objekt AssemblyBuilder använder du AssemblyBuilder.DefineDynamicAssembly -metoden. Dynamiska sammansättningar kan skapas med något av följande åtkomstlägen:
-
Den dynamiska sammansättningen som representeras av en AssemblyBuilder kan användas för att köra den avgivna koden.
AssemblyBuilderAccess.RunAndCollect
Den dynamiska sammansättningen som representeras av en AssemblyBuilder kan användas för att köra den utgivna koden och återvinns automatiskt av skräpinsamlaren.
Åtkomstläget måste anges genom att ange lämpligt AssemblyBuilderAccess värde i anropet till AssemblyBuilder.DefineDynamicAssembly metoden när den dynamiska sammansättningen definieras och inte kan ändras senare. Körningen använder åtkomstläget för en dynamisk sammansättning för att optimera sammansättningens interna representation.
I följande exempel visas hur du skapar och kör en sammansättning:
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 }));
}
Bevarade dynamiska sammansättningar i .NET
Den nya PersistedAssemblyBuilder typen som härleds från AssemblyBuilder och gör det möjligt att spara dynamiska sammansättningar i .NET Core, kontrollera användningsscenarier och exempel från sidan PersistedAssemblyBuilder .
Bevarade dynamiska sammansättningar i .NET Framework
I .NET Framework kan dynamiska sammansättningar och moduler sparas i filer. För att stödja den AssemblyBuilderAccess här funktionen deklarerar uppräkningen ytterligare två fält: Save och RunAndSave.
De dynamiska modulerna i den dynamiska sammansättningen som kan sparas sparas när den dynamiska sammansättningen sparas med hjälp av Save metoden. För att generera en körbar SetEntryPoint fil måste metoden anropas för att identifiera den metod som är startpunkten för sammansättningen. Sammansättningar sparas som standard som DLL:er, såvida inte SetEntryPoint metoden begär generering av ett konsolprogram eller ett Windows-baserat program.
I följande exempel visas hur du skapar, sparar och kör en sammansättning med hjälp av .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");
}
Vissa metoder i basklassen Assembly , till exempel GetModules
och GetLoadedModules
, fungerar inte korrekt när de anropas från AssemblyBuilder objekt. Du kan läsa in den definierade dynamiska sammansättningen och anropa metoderna för den inlästa sammansättningen. Om du till exempel vill se till att resursmoduler ingår i den returnerade modullistan anropar du GetModules
det inlästa Assembly objektet. Om en dynamisk sammansättning innehåller mer än en dynamisk modul ska sammansättningens manifestfilnamn matcha modulens namn som anges som det första argumentet till DefineDynamicModule metoden.
Signeringen av en dynamisk sammansättning med är KeyPair inte effektiv förrän sammansättningen har sparats på disken. Starka namn fungerar därför inte med tillfälliga dynamiska sammansättningar.
Dynamiska sammansättningar kan referera till typer som definierats i en annan sammansättning. En tillfällig dynamisk sammansättning kan på ett säkert sätt referera till typer som definierats i en annan tillfällig dynamisk sammansättning, en bestående dynamisk sammansättning eller en statisk sammansättning. Den vanliga språkkörningen tillåter dock inte att en dynamisk modul som kan sparas refererar till en typ som definierats i en tillfällig dynamisk modul. Det beror på att när den bevarade dynamiska modulen läses in efter att den har sparats på disken kan körningen inte matcha referenserna till typer som definierats i den tillfälliga dynamiska modulen.
Begränsningar för att skicka till fjärrprogramdomäner
Vissa scenarier kräver att en dynamisk sammansättning skapas och körs i en fjärrprogramdomän. Reflektionsemitten tillåter inte att en dynamisk sammansättning skickas direkt till en fjärrprogramdomän. Lösningen är att generera den dynamiska sammansättningen i den aktuella programdomänen, spara den avgivna dynamiska sammansättningen på disken och sedan läsa in den dynamiska sammansättningen i fjärrprogramdomänen. Fjärrkommunikations- och programdomänerna stöds endast i .NET Framework.