TypeBuilder.CreateType Метод
Определение
Важно!
Некоторые сведения относятся к предварительной версии продукта, в которую до выпуска могут быть внесены существенные изменения. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
Создает объект Type для этого класса. После определения полей и методов в классе вызывается метод CreateType
для загрузки его объекта Type
.
public:
Type ^ CreateType();
public Type? CreateType ();
public Type CreateType ();
member this.CreateType : unit -> Type
Public Function CreateType () As Type
Возвращаемое значение
Возвращает новый объект Type для этого класса.
Исключения
Включающий тип не создан.
-или-
Этот тип не является абстрактным, а содержит абстрактный метод.
-или-
Этот тип не является абстрактным классом или интерфейсом, а содержит метод без тела метода.
Неправильное содержимое метки в ILGenerator: вы определили метку без вызова MarkLabel(Label).
Тип содержит неверный код на языке MSIL.
-или-
Конечный адрес ветвления задан с использованием однобайтового смещения, но он находится на расстоянии более 127 байт от ветви.
Не удалось загрузить тип. Например, он содержит метод static
, имеющий соглашение о вызовах HasThis.
Примеры
В следующем примере кода показано, как определить обработчик событий для AppDomain.TypeResolve события, чтобы вызвать CreateType метод для вложенного типа во время CreateType вызова включающего типа.
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
Комментарии
Если этот тип является вложенным, CreateType метод должен вызываться для включающего типа, прежде чем он будет вызываться для вложенного типа.
Если текущий тип является производным от неполного типа или реализует неполные интерфейсы, вызовите CreateType метод для родительского типа и типов интерфейса, прежде чем вызывать его для текущего типа.
Если включающий тип содержит поле, которое является типом значения, определенным как вложенный тип (например, поле, представляющее собой перечисление, определенное как вложенный тип), вызов CreateType метода для включающего типа приведет к созданию AppDomain.TypeResolve события. Это связано с тем, что загрузчик не может определить размер включающего типа, пока не будет завершен вложенный тип. Вызывающий объект должен определить обработчик для события, TypeResolve чтобы завершить определение вложенного типа путем вызова CreateType объекта TypeBuilder , представляющего вложенный тип. В примере кода для этого раздела показано, как определить такой обработчик событий.
Тип создается только один раз, независимо от того, сколько раз CreateType вызывается метод. Все вызовы возвращают один и тот же Type объект.