Вы не можете полагаться на имя метода в реализующем классе - это может быть что угодно. Компиляторы 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);
Однако скажем, что мы хотим посмотреть, есть ли у реализации атрибут ответа. Тогда не будет достаточно иметь MethodInfo
для метода на интерфейсе. Имя метода было бы "LibBar.IFoo.GetAnswer"
, если бы это был C #, но мы хотим, чтобы он работал независимо от деталей реализации в компиляторе и используемом языке.
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);