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


TypeBuilder.DefineMethodOverride(MethodInfo, MethodInfo) Метод

Определение

Задает тело данного метода, реализующее объявление данного метода, возможно, с другим именем.

public:
 void DefineMethodOverride(System::Reflection::MethodInfo ^ methodInfoBody, System::Reflection::MethodInfo ^ methodInfoDeclaration);
public void DefineMethodOverride (System.Reflection.MethodInfo methodInfoBody, System.Reflection.MethodInfo methodInfoDeclaration);
member this.DefineMethodOverride : System.Reflection.MethodInfo * System.Reflection.MethodInfo -> unit
Public Sub DefineMethodOverride (methodInfoBody As MethodInfo, methodInfoDeclaration As MethodInfo)

Параметры

methodInfoBody
MethodInfo

Тело метода, которое будет использоваться. Должно быть объектом MethodBuilder.

methodInfoDeclaration
MethodInfo

Метод, объявление которого будет использоваться.

Исключения

Объект methodInfoBody не принадлежит к этому классу.

Параметр methodInfoBody или methodInfoDeclaration имеет значение null.

Этот тип был создан ранее с помощью CreateType().

-или-

Объявляющий тип methodInfoBody не является типом, представленным этим TypeBuilder.

Примеры

В следующем примере кода содержится интерфейс с методом M(), базовый классA, реализующий интерфейс , и производный классC, который переопределяет реализацию M() базового класса , а также предоставляет отдельную явную реализацию I.M().I

В main() методе примера кода показано, как создать производный класс C. Переопределение A.M() выполняется путем простого создания метода M() с той же сигнатурой. Однако, чтобы предоставить отдельную реализацию I.M(), необходимо определить тело метода, а затем использовать DefineMethodOverride метод , чтобы связать этот текст метода с представлением MethodInfoI.M(). Имя тела метода не имеет значения.

В примере кода создается экземпляр создаваемого класса. Он получает MethodInfo объект для и использует его для I.M()вызова явной реализации интерфейса выданного класса. Затем он получает MethodInfo объект для и использует его для A.M()вызова переопределения выданного класса этого метода.

using namespace System;
using namespace System::Reflection;
using namespace System::Reflection::Emit;

public interface class I 
{
    void M();
};

public ref class A 
{
public:
    virtual void M() { Console::WriteLine("In method A.M"); }
};

// The object of this code example is to emit code equivalent to
// the following C++ code:
//
public ref class C : A, I 
{
public:
    virtual void M() override 
    { 
        Console::WriteLine("Overriding A.M from C.M"); 
    }

private:
    // In order to provide a different implementation from C.M when 
    // emitting the following explicit interface implementation, 
    // it is necessary to use a MethodImpl.
    //
    virtual void IM() sealed = I::M 
    {
        Console::WriteLine("The I::M implementation of C");
    }
};

void main() 
{
    String^ name = "DefineMethodOverrideExample";
    AssemblyName^ asmName = gcnew AssemblyName(name);
    AssemblyBuilder^ ab = 
        AppDomain::CurrentDomain->DefineDynamicAssembly(
            asmName, AssemblyBuilderAccess::RunAndSave);
    ModuleBuilder^ mb = ab->DefineDynamicModule(name, name + ".dll");

    TypeBuilder^ tb = 
        mb->DefineType("C", TypeAttributes::Public, A::typeid);
    tb->AddInterfaceImplementation(I::typeid);

    // Build the method body for the explicit interface 
    // implementation. The name used for the method body 
    // can be anything. Here, it is the name of the method,
    // qualified by the interface name.
    //
    MethodBuilder^ mbIM = tb->DefineMethod("I.M", 
        MethodAttributes::Private | MethodAttributes::HideBySig |
            MethodAttributes::NewSlot | MethodAttributes::Virtual | 
            MethodAttributes::Final,
        nullptr,
        Type::EmptyTypes);
    ILGenerator^ il = mbIM->GetILGenerator();
    il->Emit(OpCodes::Ldstr, "The I.M implementation of C");
    il->Emit(OpCodes::Call, Console::typeid->GetMethod("WriteLine", 
        gcnew array<Type^> { String::typeid }));
    il->Emit(OpCodes::Ret);

    // DefineMethodOverride is used to associate the method 
    // body with the interface method that is being implemented.
    //
    tb->DefineMethodOverride(mbIM, I::typeid->GetMethod("M"));

    MethodBuilder^ mbM = tb->DefineMethod("M", 
        MethodAttributes::Public | MethodAttributes::ReuseSlot | 
            MethodAttributes::Virtual | MethodAttributes::HideBySig, 
        nullptr, 
        Type::EmptyTypes);
    il = mbM->GetILGenerator();
    il->Emit(OpCodes::Ldstr, "Overriding A.M from C.M");
    il->Emit(OpCodes::Call, Console::typeid->GetMethod("WriteLine", 
        gcnew array<Type^> { String::typeid }));
    il->Emit(OpCodes::Ret);

    Type^ tc = tb->CreateType();

    // Save the emitted assembly, to examine with Ildasm.exe.
    ab->Save(name + ".dll");

    Object^ test = Activator::CreateInstance(tc);

    MethodInfo^ mi = I::typeid->GetMethod("M");
    mi->Invoke(test, nullptr);

    mi = A::typeid->GetMethod("M");
    mi->Invoke(test, nullptr);
}

/* This code example produces the following output:

The I.M implementation of C
Overriding A.M from C.M
 */
using System;
using System.Reflection;
using System.Reflection.Emit;

public interface I
{
    void M();
}

public class A
{
    public virtual void M() { Console.WriteLine("In method A.M"); }
}

// The object of this code example is to emit code equivalent to
// the following C# code:
//
public class C : A, I
{
    public override void M()
    {
        Console.WriteLine("Overriding A.M from C.M");
    }

    // In order to provide a different implementation from C.M when
    // emitting the following explicit interface implementation,
    // it is necessary to use a MethodImpl.
    //
    void I.M()
    {
        Console.WriteLine("The I.M implementation of C");
    }
}

class Test
{
    static void Main()
    {
        string name = "DefineMethodOverrideExample";
        AssemblyName asmName = new AssemblyName(name);
        AssemblyBuilder ab =
            AppDomain.CurrentDomain.DefineDynamicAssembly(
                asmName, AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder mb = ab.DefineDynamicModule(name, name + ".dll");

        TypeBuilder tb =
            mb.DefineType("C", TypeAttributes.Public, typeof(A));
        tb.AddInterfaceImplementation(typeof(I));

        // Build the method body for the explicit interface
        // implementation. The name used for the method body
        // can be anything. Here, it is the name of the method,
        // qualified by the interface name.
        //
        MethodBuilder mbIM = tb.DefineMethod("I.M",
            MethodAttributes.Private | MethodAttributes.HideBySig |
                MethodAttributes.NewSlot | MethodAttributes.Virtual |
                MethodAttributes.Final,
            null,
            Type.EmptyTypes);
        ILGenerator il = mbIM.GetILGenerator();
        il.Emit(OpCodes.Ldstr, "The I.M implementation of C");
        il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine",
            new Type[] { typeof(string) }));
        il.Emit(OpCodes.Ret);

        // DefineMethodOverride is used to associate the method
        // body with the interface method that is being implemented.
        //
        tb.DefineMethodOverride(mbIM, typeof(I).GetMethod("M"));

        MethodBuilder mbM = tb.DefineMethod("M",
            MethodAttributes.Public | MethodAttributes.ReuseSlot |
                MethodAttributes.Virtual | MethodAttributes.HideBySig,
            null,
            Type.EmptyTypes);
        il = mbM.GetILGenerator();
        il.Emit(OpCodes.Ldstr, "Overriding A.M from C.M");
        il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine",
            new Type[] { typeof(string) }));
        il.Emit(OpCodes.Ret);

        Type tc = tb.CreateType();

        // Save the emitted assembly, to examine with Ildasm.exe.
        ab.Save(name + ".dll");

        Object test = Activator.CreateInstance(tc);

        MethodInfo mi = typeof(I).GetMethod("M");
        mi.Invoke(test, null);

        mi = typeof(A).GetMethod("M");
        mi.Invoke(test, null);
    }
}

/* This code example produces the following output:

The I.M implementation of C
Overriding A.M from C.M
 */
Imports System.Reflection
Imports System.Reflection.Emit

Public Interface I
    Sub M() 
End Interface

Public Class A
    Public Overridable Sub M() 
        Console.WriteLine("In method A.M")
    End Sub
End Class

' The object of this code example is to emit code equivalent to
' the following C# code:
'
Public Class C
    Inherits A
    Implements I
    
    Public Overrides Sub M() 
        Console.WriteLine("Overriding A.M from C.M")
    End Sub
    
    ' In order to provide a different implementation from C.M when 
    ' emitting the following explicit interface implementation, 
    ' it is necessary to use a MethodImpl.
    '
    Private Sub IM() Implements I.M
        Console.WriteLine("The I.M implementation of C")
    End Sub
End Class

Class Test
    
    Shared Sub Main() 

        Dim name As String = "DefineMethodOverrideExample"
        Dim asmName As New AssemblyName(name)
        Dim ab As AssemblyBuilder = _
            AppDomain.CurrentDomain.DefineDynamicAssembly( _
                asmName, AssemblyBuilderAccess.RunAndSave)
        Dim mb As ModuleBuilder = _
            ab.DefineDynamicModule(name, name & ".dll")
        
        Dim tb As TypeBuilder = _
            mb.DefineType("C", TypeAttributes.Public, GetType(A))
        tb.AddInterfaceImplementation(GetType(I))
        
        ' Build the method body for the explicit interface 
        ' implementation. The name used for the method body 
        ' can be anything. Here, it is the name of the method,
        ' qualified by the interface name.
        '
        Dim mbIM As MethodBuilder = _
            tb.DefineMethod("I.M", _
            MethodAttributes.Private Or MethodAttributes.HideBySig Or _
                MethodAttributes.NewSlot Or MethodAttributes.Virtual Or _
                MethodAttributes.Final, _
            Nothing, _
            Type.EmptyTypes)
        Dim il As ILGenerator = mbIM.GetILGenerator()
        il.Emit(OpCodes.Ldstr, "The I.M implementation of C")
        il.Emit(OpCodes.Call, GetType(Console).GetMethod("WriteLine", _
            New Type() {GetType(String)}))
        il.Emit(OpCodes.Ret)
        
        ' DefineMethodOverride is used to associate the method 
        ' body with the interface method that is being implemented.
        '
        tb.DefineMethodOverride(mbIM, GetType(I).GetMethod("M"))
        
        Dim mbM As MethodBuilder = tb.DefineMethod("M", _
            MethodAttributes.Public Or MethodAttributes.ReuseSlot Or _
                MethodAttributes.Virtual Or MethodAttributes.HideBySig, _
            Nothing, _
            Type.EmptyTypes)
        il = mbM.GetILGenerator()
        il.Emit(OpCodes.Ldstr, "Overriding A.M from C.M")
        il.Emit(OpCodes.Call, GetType(Console).GetMethod("WriteLine", _
            New Type() {GetType(String)}))
        il.Emit(OpCodes.Ret)
        
        Dim tc As Type = tb.CreateType()
        
        ' Save the emitted assembly, to examine with Ildasm.exe.
        ab.Save(name & ".dll")
        
        Dim test As Object = Activator.CreateInstance(tc)
        
        Dim mi As MethodInfo = GetType(I).GetMethod("M")
        mi.Invoke(test, Nothing)
        
        mi = GetType(A).GetMethod("M")
        mi.Invoke(test, Nothing)
    
    End Sub
End Class

' This code example produces the following output:
'
'The I.M implementation of C
'Overriding A.M from C.M
'

Комментарии

Не используйте этот метод для создания переопределений методов или реализаций интерфейса. Чтобы переопределить метод базового класса или реализовать метод интерфейса, просто создайте метод с тем же именем и сигнатурой, что и метод для переопределения или реализации, как показано в примере кода.

Метод DefineMethodOverride используется, когда тело метода и объявление метода имеют разные имена. Например, класс может переопределить метод базового класса, а также предоставить отдельную реализацию для члена интерфейса с тем же именем, как показано в примере кода.

DefineMethodOverride определяет methodimpl, который состоит из пары маркеров метаданных. Один маркер указывает на реализацию, а другой — на объявление, реализуемое текстом. Тело должно быть определено в типе, для который определен метод impl, и текст должен быть виртуальным (Overridable в Visual Basic). Объявление можно сделать методу, определенному в интерфейсе, реализованном типом , методу в производном классе или методу, определенному в типе . Если объявление находится только в интерфейсе, изменяется слот, определенный для интерфейса. Если объявление делается методу базового типа, слот для метода переопределяется и все дубликаты для переопределенного метода также заменяются. Переопределенный метод не может быть фактическим объявленным методом. Если метод относится к тому же типу, слот заменяется и все дубликаты для замененных методов переопределяются.

Примечание

Дополнительные сведения о методах impls смMethodImpl. в документации по метаданным раздела II ECMA на сайте ECMA C#, а также в статье Стандарты общеязыковой инфраструктуры и стандарт ECMA-335 — общеязыковая инфраструктура (CLI).

Важно!

DefineMethodOverride После вызова метода некоторые функции methodInfoBody нельзя изменить. Например, нельзя применить атрибут к параметру универсального типа с methodInfoBody помощью SetGenericParameterAttributes метода . Если необходимо использовать DefineMethodOverride метод , сделайте это после определения всех характеристик methodInfoBody .

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