开发者

How do I determine which interface is referenced by an explicitly-implemented MethodInfo object?

I have a MethodInfo object that represents an explicitly-implemented interface method, as follows.

MethodInfo GetMethod()
{
    return typeof(List<>).GetMethod(
        "Syst开发者_开发技巧em.Collections.IEnumerable.GetEnumerator",
        BindingFlags.Instance | BindingFlags.NonPublic);
}

How do I query this MethodInfo object to obtain the interface type it implements, a Type object representing System.Collections.IEnumerable? The InterfaceMapping structure provides the inverse operation, getting the MethodInfo object of a type that implements a given interface, so that won't work.

Note that this is a contrived example as I can clearly parse the method name for this information. I'd like to avoid doing this if possible.


I don't know of a direct way of doing this, but you can obviously use InterfaceMapping in reverse: iterate over all interfaces implemented by the method's declaring type, checking if the method is in the interface map for that interface:

foreach (Type itf in method.DeclaringType.GetInterfaces())
{
  if (method.DeclaringType.GetInterfaceMap(itf).TargetMethods.Any(m => m == method))
  {
    Console.WriteLine("match: " + itf.Name);
  }
}

Although this may seem a bit inefficient, most types implement few enough interfaces that it shouldn't be a big deal. Appreciate it's not terribly elegant though!


Sorry about my first answer, at first I tried getting to the method through the InterfaceMap structure, and the methods in that structure actually do report the interface as the DeclaringType. Then I tinkered with it and didn't realize it was subtly broken using the method you'd posted to get the MethodInfo.

The upside, though, is that this subtle difference led to the realization that the MethodInfo for the interface method, and the MethodInfo for the implementing method, are not actually the same method. And upon further thought, I am actually pretty sure that what you want to do is impossible to do reliably.

Explicit interface implementations in C# are a bit of syntactic sugar over the way it really works in the CLR. In other languages, a single concrete method can implement multiple interface methods the same way a concrete class can implement multiple interface types. For example, in VB.NET, it's perfectly legal to do this:

Public Overrides Function Baz() As String Implements IFoo.Foo, IBar.Bar

Here you have one method that's explicitly implementing two interface methods. If it were possible to get the original interface class - or even the original interface method - which one would you get? How do you resolve the ambiguity?

I'm not an expert on the CLR internals, but I believe that interface maps are one-way. When you implement an interface or method, implicitly or explicitly, the compiler creates a map from the interface to the implementation, and that's all it ever needs to handle method calls against the interface.

Think of the C#-generated method names as being almost coincidental. Even though the method name is System.Collections.IEnumerable.GetEnumerator, that really is just a name, and there is not actually any information about System.Collections.IEnumerable encoded in the method itself.


Try MethodInfo.DeclaringType.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜