views:

98

answers:

3

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

MethodInfo GetMethod()
{
    return typeof(List<>).GetMethod(
        "System.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.

A: 

Try MethodInfo.DeclaringType.

Marcelo Cantos
This doesn't work for explicitly implemented interface methods. It will return the type that implements the interface method, not the interface type.
Steve Guidi
+3  A: 

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!

itowlson
This is likely the only way to accomplish the search, and has the added bonus of finding __all__ interface methods that are implemented by a single method.
Steve Guidi
+1  A: 

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.

Aaronaught
Thank you for the explanation. I've also noted that when a method maps explicitly to an interface method, it need only match in signature, and not by name.
Steve Guidi