C# 反射调用方法方法 C#如何使用MethodInfo.Invoke动态调用方法
发布时间 - 2026-02-01 00:00:00 点击率:次MethodInfo.Invoke调用实例方法必须传入目标对象,传null会抛TargetException;静态方法才允许传null。泛型方法需先用MakeGenericMethod构造封闭类型,参数类型不匹配需显式转换,性能差建议缓存委托。
MethodInfo.Invoke 调用实例方法必须传入目标对象
直接对实例方法调用 MethodInfo.Invoke(null, args) 会抛出 TargetException: Object reference not set to an instance of an object。这是因为实例方法隐含一个 this 参数,反射必须知道调用在哪个对象上。
正确做法是先获取实例(比如 new 出来或从容器中取),再把该实例作为第一个参数传给 Invoke:
var obj = new Calculator();
var method = typeof(Calculator).GetMethod("Add");
var result = method.Invoke(obj, new object[] { 5, 3 }); // 返回 8
- 静态方法才允许传
null作第一个参数 - 若目标对象为
null且方法非静态,异常发生在运行时,编译不报错 - 泛型方法需先用
MakeGenericMethod构造封闭类型,再调用Invoke
参数类型不匹配会导致 TargetParameterCountException 或 ArgumentException
Invoke 不自动做类型转换,哪怕数值上兼容(如传 int 给 long 参数)也会失败。错误信息通常是 System.ArgumentException: Object of type 'System.Int32' cannot be converted to type 'System.Int64'。
解决方式是显式转换参数数组:
var args = new object[] { (long)5, (long)3 };
method.Invoke(obj, args);
- 使用
Convert.ChangeType(value, paramType)可适配更多类型组合 - 注意值类型装箱后仍是原类型,不会“升级”成父类型
- 如果参数含
ref或out,对应位置必须传object引用(如new object[] { refVar }),且调用后需手动解包
性能差、异常多,别在热路径里反复用 MethodInfo.Invoke
每次 Invoke 都要校验访问权限、参数个数、类型兼容性、执行上下文等,开销远高于直接调用。实测比直接调用慢 50–100 倍以上。
高频场景建议缓存委托:
var del = (Func)Delegate.CreateDelegate( typeof(Func ), obj, method); var result = del(5, 3); // 快,且类型安全
-
Delegate.CreateDelegate仅支持公开实例/静态方法;私有方法需用BindingFlags.NonPublic并确保有权限 - .NET 5+ 推荐用
DynamicMethod或表达式树生成委托,更灵活 - 若只是偶尔调用(如插件加载、配置驱动逻辑),
Invoke完全够用,不必过度优化
调用泛型方法前必须先构造具体类型
直接对开放泛型方法(如 List)调用 Invoke 会失败,因为 CLR 不允许执行未闭合的泛型签名。
必须用 MakeGenericMethod 显式指定类型参数:
var list = new List(); var method = typeof(List ).GetMethod("Add"); // 注意:这里 method 已是 closed 类型,可直接 Invoke method.Invoke(list, new object[] { "hello" }); // 若只有开放泛型类型(如 typeof(List<>)),则: var openMethod = typeof(List<>). GetMethod("Add"); var closedMethod = openMethod.MakeGenericMethod(typeof(string)); closedMethod.Invoke(list, new object[] { "world" });
-
MakeGenericMethod返回新MethodInfo,原对象不变 - 泛型约束(如
where T : class)会在MakeGenericMethod时检查,不满足则抛ArgumentException - 泛型类型参数不能是
var或运行时才知的Type变量——必须在调用前确定
Invoke,很容易因隐式类型丢失崩掉。
# js
# json
# c#
# .net
# gate
# gate.
# Object
# NULL
# 父类
# int
# class
# 值类型
# 参数数组
# Delegate
# 委托
# 泛型
# var
# 类型转换
# 对象
# this
# 第一个
# 先用
# 不匹配
# 直接调用
# 也会
# 都要
# 会在
# 是从
# 很容易
# 仍是
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
深圳网站制作的公司有哪些,dido官方网站?
Laravel集合Collection怎么用_Laravel集合常用函数详解
如何基于云服务器快速搭建网站及云盘系统?
如何利用DOS批处理实现定时关机操作详解
Python结构化数据采集_字段抽取解析【教程】
品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?
网页设计与网站制作内容,怎样注册网站?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
如何在建站之星网店版论坛获取技术支持?
JavaScript实现Fly Bird小游戏
香港网站服务器数量如何影响SEO优化效果?
Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】
浅析上传头像示例及其注意事项
昵图网官网入口 昵图网素材平台官方入口
如何在阿里云ECS服务器部署织梦CMS网站?
Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用
百度浏览器如何管理插件 百度浏览器插件管理方法
如何在腾讯云免费申请建站?
Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】
Android滚轮选择时间控件使用详解
C++用Dijkstra(迪杰斯特拉)算法求最短路径
Laravel Octane如何提升性能_使用Laravel Octane加速你的应用
laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法
nginx修改上传文件大小限制的方法
Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
如何生成腾讯云建站专用兑换码?
如何在七牛云存储上搭建网站并设置自定义域名?
如何快速重置建站主机并恢复默认配置?
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
网站制作软件有哪些,制图软件有哪些?
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】
详解jQuery中基本的动画方法
Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】
如何在IIS中新建站点并配置端口与IP地址?
Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】
Laravel Fortify是什么,和Jetstream有什么关系
如何实现javascript表单验证_正则表达式有哪些实用技巧
JS中对数组元素进行增删改移的方法总结
google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤
Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】
Laravel如何生成和使用数据填充?(Seeder和Factory示例)
如何用免费手机建站系统零基础打造专业网站?
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
中国移动官方网站首页入口 中国移动官网网页登录
图册素材网站设计制作软件,图册的导出方式有几种?
网站制作价目表怎么做,珍爱网婚介费用多少?
Laravel如何使用模型观察者?(Observer代码示例)
ai格式如何转html_将AI设计稿转换为HTML页面流程【页面】


