C# 反射获取方法及动态调用示例

Oliver
Oliver
发布时间:2026-10-14| 3人浏览过
原创

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# 反射技术的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。