Редактиране

Споделяне чрез


TypeBuilder.DefineMethodOverride(MethodInfo, MethodInfo) Method

Definition

Specifies a given method body that implements a given method declaration, potentially with a different name.

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)

Parameters

methodInfoBody
MethodInfo

The method body to be used. This should be a MethodBuilder object.

methodInfoDeclaration
MethodInfo

The method whose declaration is to be used.

Exceptions

methodInfoBody does not belong to this class.

methodInfoBody or methodInfoDeclaration is null.

The type was previously created using CreateType().

-or-

The declaring type of methodInfoBody is not the type represented by this TypeBuilder.

Examples

The following code example contains an interface I with a method M(), a base class A that implements the interface, and a derived class C that overrides the base class implementation of M() and also provides a separate explicit implementation of I.M().

The main() method of the code example shows how to emit the derived class C. The override of A.M() is accomplished simply by emitting a method M() with the same signature. However, to provide a separate implementation of I.M(), you must define a method body and then use the DefineMethodOverride method to associate that method body with a MethodInfo representing I.M(). The name of the method body does not matter.

The code example creates an instance of the emitted class. It obtains a MethodInfo object for I.M(), and uses it to invoke the emitted class's explicit interface implementation. It then obtains a MethodInfo object for A.M(), and uses it to invoke the emitted class's override of that method.

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
'

Remarks

Do not use this method to emit method overrides or interface implementations. To override a method of a base class or to implement a method of an interface, simply emit a method with the same name and signature as the method to be overridden or implemented, as demonstrated in the code example.

The DefineMethodOverride method is used when a method body and a method declaration have different names. For example, a class might override a base class method and also provide a separate implementation for an interface member with the same name, as demonstrated in the code example.

DefineMethodOverride defines a methodimpl, which consists of a pair of metadata tokens. One token points to an implementation, and the other token points to a declaration that the body implements. The body must be defined on the type the method impl is defined on, and the body must be virtual (Overridable in Visual Basic). The declaration can be made to a method defined on an interface implemented by the type, a method on a derived class, or a method defined in the type. If the declaration is on an interface only, the slot defined for the interface is altered. If the declaration is made to a method on a base type, the slot for the method is overridden and any duplicates for the overridden method are also replaced. The overridden method cannot be the actual method that is declared. If the method is on the same type, the slot is replaced and any duplicates for the replaced methods are overridden.

Note

For more information about method impls, see MethodImpl in the ECMA Partition II Metadata documentation at ECMA C# and Common Language Infrastructure Standards and Standard ECMA-335 - Common Language Infrastructure (CLI).

Important

After the DefineMethodOverride method is called, some features of methodInfoBody cannot be changed. For example, you cannot apply an attribute to a generic type parameter of methodInfoBody by using the SetGenericParameterAttributes method. If you must use the DefineMethodOverride method, do so after all characteristics of methodInfoBody have been defined.

Applies to