你根本不能依赖实现类的方法名——它可以是任何东西。到目前为止,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 是不够的。如果该方法是 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);