Прочитать на английском

Поделиться через


TypeBuilder.CreateType Метод

Определение

Создает объект Type для этого класса. После определения полей и методов в классе вызывается метод CreateType для загрузки его объекта Type.

public Type CreateType();
public Type? CreateType();

Возвращаемое значение

Возвращает новый объект Type для этого класса.

Исключения

Включающий тип не создан.

-или-

Этот тип не является абстрактным, а содержит абстрактный метод.

-или-

Этот тип не является абстрактным классом или интерфейсом, а содержит метод без тела метода.

Неправильное содержимое метки в ILGenerator: вы определили метку без вызова MarkLabel(Label).

Тип содержит неверный код на языке MSIL.

-или-

Конечный адрес ветвления задан с использованием однобайтового смещения, но он находится на расстоянии более 127 байт от ветви.

Не удалось загрузить тип. Например, он содержит метод static, имеющий соглашение о вызовах HasThis.

Примеры

В следующем примере кода показано, как определить обработчик событий для AppDomain.TypeResolve события, чтобы вызвать CreateType метод для вложенного типа во время CreateType вызова включающего типа.

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.Text;
using System.Resources;
using System.Collections;
using System.IO;

internal class NestedEnum {
    internal static TypeBuilder enumType = null;
    internal static Type tNested = null;
    internal static Type tNesting = null;

    public static void Main(String[] args) {
    AssemblyName asmName = new AssemblyName();
    asmName.Name = "NestedEnum";
    AssemblyBuilder asmBuild = Thread.GetDomain().DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
    ModuleBuilder modBuild = asmBuild.DefineDynamicModule("ModuleOne", "NestedEnum.dll");

    // Hook up the event listening.
    TypeResolveHandler typeResolveHandler = new TypeResolveHandler(modBuild);
    // Add a listener for the type resolve events.
    AppDomain currentDomain = Thread.GetDomain();
    ResolveEventHandler resolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveEvent);
    currentDomain.TypeResolve += resolveHandler;

    TypeBuilder tb = modBuild.DefineType("AType", TypeAttributes.Public);
    TypeBuilder eb = tb.DefineNestedType("AnEnum", TypeAttributes.NestedPublic | TypeAttributes.Sealed, typeof(Enum), null);
    eb.DefineField("value__", typeof(int), FieldAttributes.Private | FieldAttributes.SpecialName);
    FieldBuilder fb = eb.DefineField("Field1", eb, FieldAttributes.Public | FieldAttributes.Literal | FieldAttributes.Static);
    fb.SetConstant(1);

    enumType = eb;

    // Comment out this field.
    // When this field is defined, the loader cannot determine the size
    // of the type. Therefore, a TypeResolve event is generated when the
    // nested type is completed.
    tb.DefineField("Field2", eb, FieldAttributes.Public);

    tNesting = tb.CreateType();
    if (tNesting == null)
        Console.WriteLine("NestingType CreateType failed but didn't throw!");	

    try {
        tNested = eb.CreateType();
        if (tNested == null)
        Console.WriteLine("NestedType CreateType failed but didn't throw!");	
    }
    catch {
        // This is needed because you might have already completed the type in the TypeResolve event.
    }

    if (tNested != null) {
        Type x = tNested.DeclaringType;
        if (x == null)
        Console.WriteLine("Declaring type was null.");
        else
        Console.WriteLine(x.Name);
    }

    asmBuild.Save( "NestedEnum.dll" );

    // Remove the listener for the type resolve events.
    currentDomain.TypeResolve -= resolveHandler;
    }
}

// Helper class called when a resolve type event is raised.
internal class TypeResolveHandler
{
    private Module m_Module;

    public TypeResolveHandler(Module mod)
    {
    m_Module = mod;
    }

    public Assembly ResolveEvent(Object sender, ResolveEventArgs args)
    {
    Console.WriteLine(args.Name);
    // Use args.Name to look up the type name. In this case, you are getting AnEnum.
    try {
        NestedEnum.tNested = NestedEnum.enumType.CreateType();
    }
    catch {
        // This is needed to throw away InvalidOperationException.
        // Loader might send the TypeResolve event more than once
        // and the type might be complete already.
    }

    // Complete the type.		
    return m_Module.Assembly;
    }
}

Комментарии

Если этот тип является вложенным, CreateType метод должен вызываться для включающего типа, прежде чем он будет вызываться для вложенного типа.

Если текущий тип является производным от неполного типа или реализует неполные интерфейсы, вызовите CreateType метод для родительского типа и типов интерфейса, прежде чем вызывать его для текущего типа.

Если включающий тип содержит поле, которое является типом значения, определенным как вложенный тип (например, поле, представляющее собой перечисление, определенное как вложенный тип), вызов CreateType метода для включающего типа приведет к созданию AppDomain.TypeResolve события. Это связано с тем, что загрузчик не может определить размер включающего типа, пока не будет завершен вложенный тип. Вызывающий объект должен определить обработчик для события, TypeResolve чтобы завершить определение вложенного типа путем вызова CreateType объекта TypeBuilder , представляющего вложенный тип. В примере кода для этого раздела показано, как определить такой обработчик событий.

Тип создается только один раз, независимо от того, сколько раз CreateType вызывается метод. Все вызовы возвращают один и тот же Type объект.

Применяется к

Продукт Версии
.NET Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9, 10
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.1