Megosztás a következőn keresztül:


Rendszer. Önkifejezés ion. Emit.AssemblyBuilder osztály

Ez a cikk kiegészítő megjegyzéseket tartalmaz az API referenciadokumentációjához.

A dinamikus szerelvény olyan szerelvény, amely a Önkifejezés ion Emit API-kkal jön létre. A dinamikus szerelvény hivatkozhat egy másik dinamikus vagy statikus szerelvényben definiált típusokra. Segítségével AssemblyBuilder dinamikus szerelvényeket hozhat létre a memóriában, és futtathatja a kódot ugyanazon alkalmazásfuttatás során. A .NET 9-ben hozzáadtunk egy új PersistedAssemblyBuildert , amely teljes mértékben felügyelt reflexió-kibocsátással rendelkezik, amely lehetővé teszi a szerelvény fájlba mentését. A .NET-keretrendszer mindkettőt elvégezheti – futtathatja a dinamikus szerelvényt, és mentheti egy fájlba. A mentéshez létrehozott dinamikus szerelvényt állandó szerelvénynek nevezzük, míg a csak memóriával rendelkező normál szerelvényt átmenetinek vagy futtathatónak nevezzük. A .NET-keretrendszer dinamikus szerelvény egy vagy több dinamikus modulból állhat. A .NET Core és a .NET 5+ rendszerben a dinamikus szerelvények csak egy dinamikus modulból állhatnak.

A példányok létrehozásának AssemblyBuilder módja minden implementációban eltér, de a modul, típus, metódus vagy szám meghatározásának és az IL írásának további lépései meglehetősen hasonlóak.

Futtatható dinamikus szerelvények a .NET-ben

Futtatható AssemblyBuilder objektum lekéréséhez használja a metódust AssemblyBuilder.DefineDynamicAssembly . A dinamikus szerelvények az alábbi hozzáférési módok egyikével hozhatók létre:

A hozzáférési módot úgy kell megadni, hogy megadja a metódus hívásának megfelelő AssemblyBuilderAccess értékét a AssemblyBuilder.DefineDynamicAssembly dinamikus szerelvény definiálásakor, és később nem módosítható. A futtatókörnyezet egy dinamikus szerelvény hozzáférési módjával optimalizálja a szerelvény belső ábrázolását.

Az alábbi példa bemutatja, hogyan hozhat létre és futtathat szerelvényt:

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

Megőrzött dinamikus szerelvények a .NET-ben

Az új PersistedAssemblyBuilder típus a AssemblyBuilder .NET Core-ból származik, és lehetővé teszi a dinamikus szerelvények mentését, ellenőrizze a használati forgatókönyveket és példákat a PersistedAssemblyBuilder oldalról.

Megőrzött dinamikus szerelvények a .NET-keretrendszer

A .NET-keretrendszer dinamikus szerelvények és modulok menthetők fájlokba. A funkció támogatásához az AssemblyBuilderAccess enumerálás két további mezőt deklarál: Save és RunAndSave.

A megőrizhető dinamikus szerelvény dinamikus moduljai akkor lesznek mentve, ha a dinamikus szerelvényt a metódussal menti a Save rendszer. Végrehajtható fájl létrehozásához meg kell hívni a SetEntryPoint metódust, hogy azonosítsa azt a metódust, amely a szerelvény belépési pontja. A szerelvények alapértelmezés szerint DLL-ként vannak mentve, kivéve, ha a SetEntryPoint metódus egy konzolalkalmazás vagy egy Windows-alapú alkalmazás létrehozását kéri.

Az alábbi példa bemutatja, hogyan hozhat létre, menthet és futtathat szerelvényt .NET-keretrendszer használatával.

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

Az alaposztály Assembly egyes metódusai, például GetModules az és GetLoadedModules, nem működnek megfelelően, ha objektumból AssemblyBuilder hívják meg őket. Betöltheti a definiált dinamikus szerelvényt, és meghívhatja a metódusokat a betöltött szerelvényen. Ha például biztosítani szeretné, hogy az erőforrásmodulok szerepeljenek a visszaadott modullistában, hívja meg GetModules a betöltött Assembly objektumot. Ha egy dinamikus szerelvény több dinamikus modult is tartalmaz, a szerelvény jegyzékfájljának neve megegyezik a metódus első argumentumaként DefineDynamicModule megadott modul nevével.

A dinamikus szerelvény aláírása KeyPair nem érvényes addig, amíg a rendszer nem menti a szerelvényt a lemezre. Az erős nevek tehát nem működnek átmeneti dinamikus szerelvényekkel.

A dinamikus szerelvények hivatkozhatnak egy másik szerelvényben meghatározott típusokra. Az átmeneti dinamikus szerelvények biztonságosan hivatkozhatnak egy másik átmeneti dinamikus szerelvényben, egy tartósan megmaradó dinamikus szerelvényben vagy statikus szerelvényben definiált típusokra. A közös nyelvi futtatókörnyezet azonban nem teszi lehetővé, hogy egy tartós dinamikus modul egy átmeneti dinamikus modulban meghatározott típusra hivatkozzon. Ennek az az oka, hogy amikor a tárolt dinamikus modul a lemezre való mentés után betöltődik, a futtatókörnyezet nem tudja feloldani az átmeneti dinamikus modulban definiált típusokra mutató hivatkozásokat.

A távoli alkalmazástartományokra való kibocsátás korlátozásai

Egyes esetekben dinamikus szerelvényt kell létrehozni és végrehajtani egy távoli alkalmazástartományban. Önkifejezés ion-kibocsátás nem teszi lehetővé a dinamikus szerelvény közvetlen kibocsátását egy távoli alkalmazástartományba. A megoldás az, hogy az aktuális alkalmazástartományban kibocsátja a dinamikus szerelvényt, menti a kibocsátott dinamikus szerelvényt a lemezre, majd betölti a dinamikus szerelvényt a távoli alkalmazástartományba. Az újraegyezés és az alkalmazástartományok csak .NET-keretrendszer támogatottak.