Usually, I access a method in reflection like this:
class Foo
{
public void M () {
var m = this.GetType ().GetMethod ("M");
m.Invoke(this, new object[] {}); // notice the pun
}
}
However, this fails when M is an explicit implementation:
class Foo : SomeBase
{
void SomeBase.M () {
var m = this.GetType ().GetMethod ("M");
m.Invoke(this, new object[] {}); // fails as m is null
}
}
How do I access an explicitly implemented method using reflection?
It's because the name of the method is not "M"
, it will be "YourNamespace.SomeBase.M"
. So either you will need to specify that name (along with appropriate BindingFlags
), or get the method from the interface type instead.
So given the following structure:
namespace SampleApp
{
interface IFoo
{
void M();
}
class Foo : IFoo
{
void IFoo.M()
{
Console.WriteLine("M");
}
}
}
...you can do either this:
Foo obj = new Foo();
obj.GetType()
.GetMethod("SampleApp.IFoo.M", BindingFlags.Instance | BindingFlags.NonPublic)
.Invoke(obj, null);
...or this:
Foo obj = new Foo();
typeof(IFoo)
.GetMethod("M")
.Invoke(obj, null);
You cannot rely on the name of the method on the implementing class at all - it can be anything. The C# compilers have so far used the convention of prefixing the method name with the fullname of the interface, but that is an internal implementation detail, and also won't be true for e.g. F#. The proper way is by using InterfaceMapping
if you want a MethodInfo
for the implementation.
For example if we have the following structure
namespace LibBar
{
[AttributeUsage(AttributeTargets.Method)]
public class AnswerAttribute : Attribute { }
public interface IFoo
{
void Hello();
int GetAnswer();
object WhoAmI();
}
}
And in an F# project
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
If we just want to call GetAnswer()
through reflection then it suffices to get the MethodInfo
for the interface
Foo obj = new Foo();
int answer = (int)typeof(IFoo)
.GetMethod("GetAnswer")
.Invoke(obj, null);
However say that we want to see if the implementation has the AnswerAttribute. Then it won't be enough to just have the MethodInfo
for the method on the interface. The name of the method would be "LibBar.IFoo.GetAnswer"
if this had been C#, but we want it to work independent of implementation details in the compiler and language used.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With