System. Emocje ion. Emit.AssemblyBuilder, klasa

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Zestaw dynamiczny to zestaw tworzony przy użyciu interfejsów API emisji Emocje ion. Zestaw dynamiczny może odwoływać się do typów zdefiniowanych w innym zestawie dynamicznym lub statycznym. Możesz użyć AssemblyBuilder polecenia , aby wygenerować zestawy dynamiczne w pamięci i wykonać ich kod podczas tego samego uruchomienia aplikacji. Na platformie .NET 9 dodaliśmy nowy element PersistedAssemblyBuilder z w pełni zarządzaną implementacją emisji odbicia, która umożliwia zapisanie zestawu w pliku. W programie .NET Framework możesz uruchomić zestaw dynamiczny i zapisać go w pliku. Zestaw dynamiczny utworzony do zapisywania jest nazywany utrwalonego zestawu, podczas gdy zwykły zestaw tylko do pamięci jest nazywany przejściowym lub uruchamianym. W programie .NET Framework zestaw dynamiczny może składać się z co najmniej jednego modułu dynamicznego. W programach .NET Core i .NET 5+zestaw dynamiczny może składać się tylko z jednego modułu dynamicznego.

Sposób tworzenia AssemblyBuilder wystąpienia różni się w przypadku każdej implementacji, ale dalsze kroki definiowania modułu, typu, metody lub wyliczenia i pisania języka IL są dość podobne.

Zestawy dynamiczne z możliwością uruchamiania na platformie .NET

Aby uzyskać obiekt możliwy do AssemblyBuilder uruchomienia, użyj AssemblyBuilder.DefineDynamicAssembly metody . Zestawy dynamiczne można tworzyć przy użyciu jednego z następujących trybów dostępu:

Tryb dostępu musi być określony przez podanie odpowiedniej AssemblyBuilderAccess wartości w wywołaniu AssemblyBuilder.DefineDynamicAssembly metody, gdy zestaw dynamiczny jest zdefiniowany i nie można go zmienić później. Środowisko uruchomieniowe używa trybu dostępu zestawu dynamicznego, aby zoptymalizować wewnętrzną reprezentację zestawu.

W poniższym przykładzie pokazano, jak utworzyć i uruchomić zestaw:

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

Utrwalone zestawy dynamiczne na platformie .NET

Nowy PersistedAssemblyBuilder typ pochodzący z elementu AssemblyBuilder i umożliwia zapisywanie zestawów dynamicznych na platformie .NET Core, sprawdzanie scenariuszy użycia i przykładów ze strony PersistedAssemblyBuilder .

Utrwalone zestawy dynamiczne w programie .NET Framework

W programie .NET Framework zestawy dynamiczne i moduły można zapisywać w plikach. Aby obsługiwać tę funkcję, AssemblyBuilderAccess wyliczenie deklaruje dwa dodatkowe pola: Save i RunAndSave.

Moduły dynamiczne w trwałym zestawie dynamicznym są zapisywane podczas zapisywania zestawu dynamicznego Save przy użyciu metody . Aby wygenerować plik wykonywalny, należy wywołać metodę , SetEntryPoint aby zidentyfikować metodę, która jest punktem wejścia do zestawu. Zestawy są domyślnie zapisywane jako biblioteki DLL, chyba że SetEntryPoint metoda żąda generowania aplikacji konsolowej lub aplikacji opartej na systemie Windows.

W poniższym przykładzie pokazano, jak utworzyć, zapisać i uruchomić zestaw przy użyciu programu .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");
}

Niektóre metody w klasie bazowej Assembly , takie jak GetModules i GetLoadedModules, nie będą działać poprawnie po wywołaniu z AssemblyBuilder obiektów. Można załadować zdefiniowany zestaw dynamiczny i wywołać metody w załadowanym zestawie. Aby na przykład upewnić się, że moduły zasobów znajdują się na liście zwróconych modułów, wywołaj GetModules załadowany Assembly obiekt. Jeśli zestaw dynamiczny zawiera więcej niż jeden moduł dynamiczny, nazwa pliku manifestu zestawu powinna być zgodna z nazwą modułu, która jest określona jako pierwszy argument metody DefineDynamicModule .

Podpisywanie zestawu dynamicznego przy użyciu polecenia KeyPair nie jest skuteczne, dopóki zestaw nie zostanie zapisany na dysku. Tak więc silne nazwy nie będą działać z przejściowymi zestawami dynamicznymi.

Zestawy dynamiczne mogą odwoływać się do typów zdefiniowanych w innym zestawie. Zestaw dynamiczny przejściowy może bezpiecznie odwoływać się do typów zdefiniowanych w innym zestawie dynamicznym przejściowym, trwałym zestawie dynamicznym lub zestawie statycznym. Jednak środowisko uruchomieniowe języka wspólnego nie zezwala na trwały moduł dynamiczny odwołujące się do typu zdefiniowanego w module dynamicznym przejściowym. Dzieje się tak, ponieważ gdy utrwalone moduły dynamiczne są ładowane po zapisaniu na dysku, środowisko uruchomieniowe nie może rozpoznać odwołań do typów zdefiniowanych w module dynamicznym przejściowym.

Ograniczenia emisji do zdalnych domen aplikacji

Niektóre scenariusze wymagają utworzenia i wykonania zestawu dynamicznego w domenie aplikacji zdalnej. emisja Emocje ion nie zezwala na emisję zestawu dynamicznego bezpośrednio do domeny aplikacji zdalnej. Rozwiązaniem jest emitować zestaw dynamiczny w bieżącej domenie aplikacji, zapisać emitowany zestaw dynamiczny na dysku, a następnie załadować zestaw dynamiczny do domeny aplikacji zdalnej. Komunikacja zdalna i domeny aplikacji są obsługiwane tylko w programie .NET Framework.