英語で読む

次の方法で共有


TypeBuilder.DefineMethodOverride(MethodInfo, MethodInfo) メソッド

定義

特定のメソッド宣言 (名前が異なる可能性があります) を実装する特定のメソッド本体を指定します。

C#
public void DefineMethodOverride(System.Reflection.MethodInfo methodInfoBody, System.Reflection.MethodInfo methodInfoDeclaration);

パラメーター

methodInfoBody
MethodInfo

使用するメソッド本体。 これは MethodBuilder オブジェクトである必要があります。

methodInfoDeclaration
MethodInfo

宣言が使用されるメソッド。

例外

methodInfoBody はこのクラスに属していません。

methodInfoBody または methodInfoDeclarationnull です。

型は CreateType() を使用して既に作成されました。

- または -

methodInfoBody の宣言型は、この TypeBuilder によって表される型ではありません。

次のコード例には、 メソッドM()を持つインターフェイスI、インターフェイスを実装する基底クラスA、および の基本クラスの実装M()をオーバーライドし、 の個別の明示的な実装I.M()も提供する派生クラスCが含まれています。

コード例の メソッドは main() 、派生クラス Cを出力する方法を示しています。 の A.M() オーバーライドは、同じシグネチャを持つメソッド M() を出力するだけで実現されます。 ただし、 の個別の I.M()実装を提供するには、メソッド本体を定義してから、 メソッドを DefineMethodOverride 使用してそのメソッド本体 MethodInfo を を表す I.M()に関連付ける必要があります。 メソッド本体の名前は関係ありません。

このコード例では、出力されたクラスのインスタンスを作成します。 の オブジェクトI.M()MethodInfo取得し、それを使用して出力されたクラスの明示的なインターフェイス実装を呼び出します。 次に、 の A.M()オブジェクトをMethodInfo取得し、それを使用してそのメソッドの出力されたクラスのオーバーライドを呼び出します。

C#
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
 */

注釈

メソッドのオーバーライドまたはインターフェイスの実装を出力するには、このメソッドを使用しないでください。 基底クラスのメソッドをオーバーライドしたり、インターフェイスのメソッドを実装したりするには、コード例で示すように、オーバーライドまたは実装するメソッドと同じ名前とシグネチャを持つメソッドを生成するだけです。

メソッドは DefineMethodOverride 、メソッド本体とメソッド宣言の名前が異なる場合に使用されます。 たとえば、クラスは基底クラスメソッドをオーバーライドし、コード例で示すように、同じ名前のインターフェイス メンバーに対して個別の実装を提供する場合があります。

DefineMethodOverride は、 methodimplメタデータ トークンのペアで構成される を定義します。 1 つのトークンは実装を指し、もう 1 つのトークンは本体が実装する宣言を指します。 本体は、メソッド impl が定義されている型で定義する必要があり、本文は virtual ( Visual Basic では )Overridable である必要があります。 宣言は、型によって実装されるインターフェイスで定義されたメソッド、派生クラスのメソッド、または型で定義されたメソッドに対して行うことができます。 宣言がインターフェイスのみの場合は、インターフェイスに対して定義されているスロットが変更されます。 基本型のメソッドに対して宣言が行われた場合、メソッドのスロットがオーバーライドされ、オーバーライドされたメソッドの重複も置き換えられます。 オーバーライドされたメソッドを、宣言されている実際のメソッドにすることはできません。 メソッドが同じ型の場合、スロットが置き換えられ、置き換えられたメソッドの重複がオーバーライドされます。

注意

メソッド の実装の詳細については、MethodImplECMA C# と共通言語インフラストラクチャ標準および標準 ECMA-335 - 共通言語インフラストラクチャ (CLI) の ECMA Partition II メタデータに関するドキュメントを参照してください。

重要

メソッドが DefineMethodOverride 呼び出されると、 の一部の methodInfoBody 機能を変更できません。 たとえば、 メソッドを使用して のジェネリック型パラメーター methodInfoBody に属性を SetGenericParameterAttributes 適用することはできません。 メソッドを使用する DefineMethodOverride 必要がある場合は、 のすべての特性が methodInfoBody 定義された後に行います。

適用対象

製品 バージョン
.NET Core 1.0, Core 1.1, 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.0 (package-provided), 2.1