TypeBuilder.CreateType Método

Definição

Cria um objeto Type para a classe. Depois de definir campos e métodos na classe, CreateType é chamado para carregar seu objeto Type.

public:
 Type ^ CreateType();
public Type? CreateType ();
public Type CreateType ();
member this.CreateType : unit -> Type
Public Function CreateType () As Type

Retornos

Retorna o novo objeto Type dessa classe.

Exceções

O tipo delimitador não foi criado.

- ou -

Esse tipo é não abstrato e contém um método abstrato.

- ou -

Esse tipo não é uma classe abstrata nem uma interface e tem um método sem um corpo do método.

Conteúdo de rótulo inadequado em ILGenerator: você definiu um rótulo sem chamar MarkLabel(Label).

O tipo contém código MSIL (Microsoft Intermediate Language) inválido.

- ou -

O destino da ramificação é especificado usando um deslocamento de 1 byte, mas está em uma distância maior que 127 bytes da ramificação.

O tipo não pode ser carregado. Por exemplo, contém um método static com a convenção de chamada HasThis.

Exemplos

O exemplo de código a seguir mostra como definir um manipulador de eventos para o AppDomain.TypeResolve evento, a fim de chamar o CreateType método em um tipo aninhado durante uma CreateType chamada no tipo delimitado.

using namespace System;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
using namespace System::Threading;
using namespace System::Text;
using namespace System::Resources;
using namespace System::Collections;
using namespace System::IO;

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

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

   Assembly^ ResolveEvent( Object^ sender, ResolveEventArgs^ args );
};

ref class NestedEnum
{
internal:
   static TypeBuilder^ enumType = nullptr;
   static Type^ tNested = nullptr;
   static Type^ tNesting = nullptr;

public:
   static void Main()
   {
      AssemblyName^ asmName = gcnew 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 = gcnew TypeResolveHandler( modBuild );
      
      // Add a listener for the type resolve events.
      AppDomain^ currentDomain = Thread::GetDomain();
      ResolveEventHandler^ resolveHandler = gcnew ResolveEventHandler( typeResolveHandler, &TypeResolveHandler::ResolveEvent );
      currentDomain->TypeResolve += resolveHandler;
      TypeBuilder^ tb = modBuild->DefineType( "AType", TypeAttributes::Public );
      TypeBuilder^ eb = tb->DefineNestedType( "AnEnum", static_cast<TypeAttributes>(TypeAttributes::NestedPublic | TypeAttributes::Sealed), Enum::typeid, 0 );
      eb->DefineField( "value__", int::typeid, static_cast<FieldAttributes>(FieldAttributes::Private | FieldAttributes::SpecialName) );
      FieldBuilder^ fb = eb->DefineField( "Field1", eb, static_cast<FieldAttributes>(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 == nullptr )
            Console::WriteLine( "NestingType CreateType failed but didn't throw!" );

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

      if ( tNested != nullptr )
      {
         Type^ x = tNested->DeclaringType;
         if ( x == nullptr )
                  Console::WriteLine( "Declaring type is null." );
         else
                  Console::WriteLine( x->Name );
      }

      asmBuild->Save( "NestedEnum.dll" );
      
      // Remove the listener for the type resolve events.
      currentDomain->TypeResolve -= resolveHandler;
   }

};

Assembly^ TypeResolveHandler::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 ( Exception^ ) 
   {
      
      // 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;
}

int main()
{
   NestedEnum::Main();
}
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;
    }
}
Imports System.Reflection
Imports System.Reflection.Emit
Imports System.Threading
Imports System.Text
Imports System.Resources
Imports System.Collections
Imports System.IO

Friend Class NestedEnum
   Friend Shared enumType As TypeBuilder = Nothing
   Friend Shared tNested As Type = Nothing
   Friend Shared tNesting As Type = Nothing
   
   Public Shared Sub Main()
      Dim asmName As New AssemblyName()
      asmName.Name = "NestedEnum"
      Dim asmBuild As AssemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave)
      Dim modBuild As ModuleBuilder = asmBuild.DefineDynamicModule("ModuleOne", "NestedEnum.dll")
      
      ' Hook up the event listening.
      Dim typeResolveHandler As New TypeResolveHandler(modBuild)
      ' Add a listener for the type resolve events.
      Dim currentDomain As AppDomain = Thread.GetDomain()
      Dim resolveHandler As ResolveEventHandler = AddressOf typeResolveHandler.ResolveEvent
      AddHandler currentDomain.TypeResolve, resolveHandler 
      
      Dim tb As TypeBuilder = modBuild.DefineType("AType", TypeAttributes.Public)
      Dim eb As TypeBuilder = tb.DefineNestedType("AnEnum", TypeAttributes.NestedPublic Or TypeAttributes.Sealed, GetType([Enum]))
      eb.DefineField("value__", GetType(Integer), FieldAttributes.Private Or FieldAttributes.SpecialName)
      Dim fb As FieldBuilder = eb.DefineField("Field1", eb, FieldAttributes.Public Or FieldAttributes.Literal Or 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 Is Nothing Then
         Console.WriteLine("NestingType CreateType failed but didn't throw!")
      End If 
      Try
         tNested = eb.CreateType()
         If tNested Is Nothing Then
            Console.WriteLine("NestedType CreateType failed but didn't throw!")
         End If
      Catch
      End Try ' This is needed because you might have already completed the type in the TypeResolve event.
      
      If Not (tNested Is Nothing) Then
         Dim x As Type = tNested.DeclaringType
         If x Is Nothing Then
            Console.WriteLine("Declaring type is Nothing.")
         Else
            Console.WriteLine(x.Name)
         End If
      End If 
      asmBuild.Save("NestedEnum.dll")
      
      ' Remove the listener for the type resolve events.
      RemoveHandler currentDomain.TypeResolve, resolveHandler 
   End Sub
End Class


' Helper class called when a resolve type event is raised.
Friend Class TypeResolveHandler
   Private m_Module As [Module]
   
   
   Public Sub New([mod] As [Module])
      m_Module = [mod]
   End Sub
   
   
   Public Function ResolveEvent(sender As [Object], args As ResolveEventArgs) As [Assembly]
      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
      End Try ' 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
   End Function 'ResolveEvent
End Class

Comentários

Se esse tipo for um tipo aninhado, o CreateType método deverá ser chamado no tipo delimitado antes de ser chamado no tipo aninhado.

Se o tipo atual derivar de um tipo incompleto ou implementar interfaces incompletas, chame o CreateType método no tipo pai e os tipos de interface antes de chamá-lo no tipo atual.

Se o tipo delimitador contiver um campo que é um tipo de valor definido como um tipo aninhado (por exemplo, um campo que é uma enumeração definida como um tipo aninhado), chamar o CreateType método no tipo delimitador gerará um AppDomain.TypeResolve evento. Isso ocorre porque o carregador não pode determinar o tamanho do tipo delimitador até que o tipo aninhado tenha sido concluído. O chamador deve definir um manipulador para que o TypeResolve evento conclua a definição do tipo aninhado chamando CreateType no TypeBuilder objeto que representa o tipo aninhado. O exemplo de código para este tópico mostra como definir esse manipulador de eventos.

Um tipo é criado apenas uma vez, independentemente de quantas vezes o CreateType método é chamado. Todas as chamadas retornam o mesmo Type objeto.

Aplica-se a