您根本不能依赖实现类上的方法名称——它可以是任何东西。到目前为止,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 方法是不够的。如果这是 C#,方法的名称将是"LibBar.IFoo.GetAnswer"
,但我们希望它独立于编译器和使用的语言中的实现细节而工作。
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);