11

通常、私は次のようなリフレクションのメソッドにアクセスします。

class Foo
{
    public void M () {
        var m = this.GetType ().GetMethod ("M");
        m.Invoke(this, new object[] {}); // notice the pun
    }
}

ただし、Mが明示的な実装である場合、これは失敗します。

class Foo : SomeBase
{
    void SomeBase.M () {
        var m = this.GetType ().GetMethod ("M");
        m.Invoke(this, new object[] {}); // fails as m is null
    }
}

リフレクションを使用して明示的に実装されたメソッドにアクセスするにはどうすればよいですか?

4

2 に答える 2

15

メソッドの名前がではないため"M"、になります"YourNamespace.SomeBase.M"。したがって、その名前を(適切なものとともにBindingFlags)指定するか、代わりにインターフェイスタイプからメソッドを取得する必要があります。

したがって、次の構造が与えられます。

namespace SampleApp
{    
    interface IFoo
    {
        void M();
    }

    class Foo : IFoo
    {
        void IFoo.M()
        {
            Console.WriteLine("M");
        }
    }
}

...次のいずれかを実行できます。

Foo obj = new Foo();
obj.GetType()
    .GetMethod("SampleApp.IFoo.M", BindingFlags.Instance | BindingFlags.NonPublic)
    .Invoke(obj, null);            

...またはこれ:

Foo obj = new Foo();
typeof(IFoo)
    .GetMethod("M")
    .Invoke(obj, null);  
于 2010-09-06T10:16:04.500 に答える
3

実装クラスのメソッドの名前はまったく信頼できません。どのような名前でもかまいません。C#コンパイラはこれまで、メソッド名の前にインターフェイスのフルネームを付けるという規則を使用してきましたが、これは内部実装の詳細であり、F#などには当てはまりません。適切な方法は、実装にInterfaceMappingを必要とする場合に使用することです。MethodInfo

たとえば、次の構造がある場合

namespace LibBar
{
  [AttributeUsage(AttributeTargets.Method)]
  public class AnswerAttribute : Attribute { }

  public interface IFoo
  {
    void Hello();
    int GetAnswer();
    object WhoAmI();
  }
}

そしてF#プロジェクトでは

namespace LibFoo
open LibBar

type Foo() = 
    interface IFoo with
        [<Answer>]
        member this.GetAnswer() = 42
        member this.Hello() = printf "Hello, World!"
        member this.WhoAmI() = this :> obj

GetAnswer()リフレクションを介して呼び出したいだけの場合はMethodInfo、インターフェイスのを取得するだけで十分です。

Foo obj = new Foo();
int answer = (int)typeof(IFoo)
  .GetMethod("GetAnswer")
  .Invoke(obj, null);

ただし、実装にAnswerAttributeがあるかどうかを確認したいとします。MethodInfoその場合、インターフェイスにforメソッドを設定するだけでは不十分です。メソッドの名前は、"LibBar.IFoo.GetAnswer"これがC#の場合ですが、使用するコンパイラーと言語の実装の詳細に関係なく機能するようにします。

private static MethodInfo GetMethodImplementation(Type implementationType, MethodInfo ifaceMethod)
{
  InterfaceMapping ifaceMap = implementationType.GetInterfaceMap(ifaceMethod.DeclaringType);
  for (int i = 0; i < ifaceMap.InterfaceMethods.Length; i++)
  {
    if (ifaceMap.InterfaceMethods[i].Equals(ifaceMethod))
      return ifaceMap.TargetMethods[i];
  }
  throw new Exception("Method missing from interface mapping??"); // We shouldn't get here
}

...

  Foo obj = new Foo();
  MethodInfo ifaceMethod = typeof(IFoo).GetMethod("GetAnswer");
  MethodInfo implementationMethod = GetMethodImplementation(typeof(Foo), ifaceMethod);
  Console.WriteLine("GetAnswer(): {0}, has AnswerAttribute: {1}",
    implementationMethod.Invoke(obj, null),
    implementationMethod.GetCustomAttribute<AnswerAttribute>() != null);
于 2018-10-10T15:11:55.190 に答える