ang*_*son 3 c# reflection interface methodinfo
我的问题是这样的:如果我有MethodInfo对象,对于一个方法,从一个接口类型得到的,我也有一个实现此接口的类的类型的对象,但它有一个明确的实施实现了该方法,如何为该类中的实现方法正确获取相应的MethodInfo对象?
我需要这样做的原因是实现方法可以有一些属性应用于它们,我需要通过反射找到它们,但是需要找到这些属性的类只有实现类的对象引用,以及类型对象(+对应的MethodInfo对象)用于接口.
所以,我们假设我有以下程序:
using System;
using System.Reflection;
namespace ConsoleApplication8
{
public interface ITest
{
void Test();
}
public class Test : ITest
{
void ITest.Test()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
Type interfaceType = typeof(ITest);
Type classType = typeof(Test);
MethodInfo testMethodViaInterface =
interfaceType.GetMethods()[0];
MethodInfo implementingMethod =
classType.GetMethod(/* ??? */"Test");
Console.Out.WriteLine("interface: " +
testMethodViaInterface.Name);
if (implementingMethod != null)
Console.Out.WriteLine("class: " +
implementingMethod.Name);
else
Console.Out.WriteLine("class: unable to locate");
Console.Out.Write("Press enter to exit...");
Console.In.ReadLine();
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行这个给了我:
interface: Test
class: unable to locate
Press enter to exit...
Run Code Online (Sandbox Code Playgroud)
在代码中有一个.GetMethod调用带??? 评论.这部分是我需要帮助的部分.要么我需要在这里指定(我已经测试了很多,这会带我到另一个方向)或者我需要用什么代替这个代码.
由于我在界面中使用了方法的显式实现,因此方法的实际名称不仅仅是"Test".如果我转储类类型的GetMethods()数组的全部内容,使用以下代码:
foreach (var mi in classType.GetMethods(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
Console.Out.WriteLine(mi.Name);
}
Run Code Online (Sandbox Code Playgroud)
然后我明白了:
ConsoleApplication8.ITest.Test <-- this is the one I want
ToString
Equals
GetHashCode
GetType
Finalize
MemberwiseClone
Run Code Online (Sandbox Code Playgroud)
很明显,该名称具有接口的全名及其前面的命名空间.但是,由于重载,我要做的就是在类中找到所有这样的实现方法(即假设有多个Test方法因参数而异),然后比较参数.
有没有更简单的方法?基本上我想,一旦我从一个接口的方法获得MethodInfo对象,就可以通过获取它的MethodInfo对象来找到实现此方法的类的确切方法.
请注意,我在一个糊涂这里的情况,所以如果我通过在类中的方法必须循环,以找到界面的具体方法,没关系,只要我有一个很好的方法来识别时,我已经找到了正确对象,真爱.
我试着像这样改变上面的循环:
foreach (var mi in classType.GetMethods(
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
if (mi.GetBaseDefinition() == testMethodViaInterface)
Console.Out.WriteLine(mi.Name);
}
Run Code Online (Sandbox Code Playgroud)
这没有打印出任何东西,所以很明显GetBaseDefinition这样的方法并没有从接口指向MethodInfo对象.
有什么指针吗?
ang*_*son 10
对于未来的参考,如果其他人有兴趣,通过给我的解决方案@格雷格榉 这里是使用Type.GetInterfaceMap.
这是改变的程序代码,底部有一个扩展方法.
using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
namespace ConsoleApplication8
{
public interface ITest
{
void Test();
}
public class Test : ITest
{
void ITest.Test()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
Type interfaceType = typeof(ITest);
Type classType = typeof(Test);
InterfaceMapping map = classType.GetInterfaceMap(interfaceType);
MethodInfo testMethodViaInterface = interfaceType.GetMethods()[0];
MethodInfo implementingMethod = testMethodViaInterface.GetImplementingMethod(classType);
Console.Out.WriteLine("interface: " + testMethodViaInterface.Name);
if (implementingMethod != null)
Console.Out.WriteLine("class: " + implementingMethod.Name);
else
Console.Out.WriteLine("class: unable to locate");
Console.Out.Write("Press enter to exit...");
Console.In.ReadLine();
}
}
public static class TypeExtensions
{
/// <summary>
/// Gets the corresponding <see cref="MethodInfo"/> object for
/// the method in a class that implements a specific method
/// from an interface.
/// </summary>
/// <param name="interfaceMethod">
/// The <see cref="MethodInfo"/> for the method to locate the
/// implementation of.</param>
/// <param name="classType">
/// The <see cref="Type"/> of the class to find the implementing
/// method for.
/// </param>
/// <returns>
/// The <see cref="MethodInfo"/> of the method that implements
/// <paramref name="interfaceMethod"/>.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <para><paramref name="interfaceMethod"/> is <c>null</c>.</para>
/// <para>- or -</para>
/// <para><paramref name="classType"/> is <c>null</c>.</para>
/// </exception>
/// <exception cref="ArgumentException">
/// <para><paramref name="interfaceMethod"/> is not defined in an interface.</para>
/// </exception>
public static MethodInfo GetImplementingMethod(this MethodInfo interfaceMethod, Type classType)
{
#region Parameter Validation
if (Object.ReferenceEquals(null, interfaceMethod))
throw new ArgumentNullException("interfaceMethod");
if (Object.ReferenceEquals(null, classType))
throw new ArgumentNullException("classType");
if (!interfaceMethod.DeclaringType.IsInterface)
throw new ArgumentException("interfaceMethod", "interfaceMethod is not defined by an interface");
#endregion
InterfaceMapping map = classType.GetInterfaceMap(interfaceMethod.DeclaringType);
MethodInfo result = null;
for (Int32 index = 0; index < map.InterfaceMethods.Length; index++)
{
if (map.InterfaceMethods[index] == interfaceMethod)
result = map.TargetMethods[index];
}
Debug.Assert(result != null, "Unable to locate MethodInfo for implementing method");
return result;
}
}
}
Run Code Online (Sandbox Code Playgroud)