C# 反射获取方法及动态调用示例
C# 反射允许程序在运行时动态获取类型信息和调用方法。通过 Type 对象和 BindingFlags 枚举可以精确筛选所需成员,利用 MethodInfo.Invoke 实现方法的动态执行。
获取类型信息及方法列表
在 .NET 中,System.Type 对象是反射的核心,它映射了底层对象的元数据。一旦获得 Type 实例,即可通过以下两种方式获取支持的方法列表:
第一步:获取所有公开方法
调用 GetMethods() 无参版本时,该方法会返回包含基类(如 object)在内的所有公开方法。这通常会导致结果中包含大量非预期方法,适用于仅需粗略查看的情况。
第二步:使用 BindingFlags 过滤方法
为了仅获取当前类声明的特定成员,需使用带参数的 GetMethods(BindingFlags bindingFlags)。通过组合枚举标志,可以精确控制检索范围。常用的标志包括:
DeclaredOnly:仅搜索在当前类中直接声明的成员,不包括从基类继承的成员。Instance:指定实例方法或字段。Public:指定公共成员。
此外,可以通过 ParameterInfo[] GetParameters() 获取具体方法的参数详情,从而进行更细致的匹配。
示例:MyClass 定义
以下为用于演示的测试类,包含构造函数、不同签名的 Set 方法及属性访问方法:
class MyClass
{
int x;
int y;
public MyClass(int i, int j)
{
this.x = i;
this.y = j;
}
public int Sum()
{
return x + y;
}
public bool IsBetween(int i)
{
if (x < i && i < y)
return true;
return false;
}
public void Set(int a, int b)
{
Console.WriteLine("Set(int,int)");
x = a;
y = b;
Show();
}
public void Set(double a, double b)
{
Console.WriteLine("Set(double,double)");
x = (int)a;
y = (int)b;
Show();
}
public void Show()
{
Console.WriteLine("x: " + x + " y: " + y);
}
}
使用反射动态调用方法
获取到 MethodInfo 后,核心操作是通过 Invoke 方法执行目标逻辑。其基本语法为:object Invoke(object obj, object[] parameters)。
第三步:构造调用参数并执行
1. 参数说明:obj 是要调用该方法的实例对象;若为静态方法,此参数应为 null。parameters 数组包含传递给方法的实际参数值,若无参数则传 null。
2. 返回值处理:方法执行后的返回值被封装在 object 中,需根据原方法签名进行强制类型转换。
第四步:处理方法重载与匹配
当类中存在多个同名但参数不同的重载方法时,需先遍历所有方法,通过名称和参数类型进行匹配,确定目标 MethodInfo 后再执行调用。推荐使用 StringComparison.Ordinal 进行字符串比较以优化性能。
示例:动态调用逻辑
Type t = typeof(MyClass);
MyClass reflectOb = new MyClass(10, 20);
Console.WriteLine("Invoke methods in " + t.Name);
MethodInfo[] mi = t.GetMethods();
foreach (MethodInfo m in mi)
{
ParameterInfo[] pi = m.GetParameters();
// 匹配 Set(int, int)
if (m.Name.Equals("Set", StringComparison.Ordinal) && pi.Length == 2 && pi[0].ParameterType == typeof(int))
{
object[] obj = new object[2];
obj[0] = 9;
obj[1] = 18;
m.Invoke(reflectOb, obj);
}
// 匹配 Set(double, double)
else if (m.Name.Equals("Set", StringComparison.Ordinal) && pi.Length == 2 && pi[0].ParameterType == typeof(double))
{
object[] obj = new object[2];
obj[0] = 1.12;
obj[1] = 23.4;
m.Invoke(reflectOb, obj);
}
// 匹配 Sum() - 无参数
else if (m.Name.Equals("Sum", StringComparison.Ordinal) && pi.Length == 0)
{
int val = (int)m.Invoke(reflectOb, null);
Console.WriteLine("Sum is : " + val);
}
// 匹配 IsBetween(int)
else if (m.Name.Equals("IsBetween", StringComparison.Ordinal) && pi.Length == 1)
{
object[] obj = new object[1];
obj[0] = 14;
if ((bool)m.Invoke(reflectOb, obj))
{
Console.WriteLine("14 is between x and y");
}
}
// 匹配 Show() - 无参数
else if (m.Name.Equals("Show", StringComparison.Ordinal) && pi.Length == 0)
{
m.Invoke(reflectOb, null);
}
}
完成判断与总结
成功输出各方法预期的日志信息及计算结果,即表示反射调用流程正确。掌握通过 BindingFlags 精准定位方法和 Invoke 动态传参的技巧,可大幅提升 C# 代码的动态扩展能力。
以上就是 C# 反射获取方法及动态调用的详细内容,更多关于 C# 反射技术的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









