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<int, int, int>)Delegate.CreateDelegate(
typeof(Func<int, int, int>), obj, method);
var result = del(5, 3); // 快,且类型安全
-
Delegate.CreateDelegate仅支持公开实例/静态方法;私有方法需用BindingFlags.NonPublic并确保有权限 - .NET 5+ 推荐用
DynamicMethod或表达式树生成委托,更灵活 - 若只是偶尔调用(如插件加载、配置驱动逻辑),
Invoke完全够用,不必过度优化
调用泛型方法前必须先构造具体类型
直接对开放泛型方法(如 List<T>.Add(T))调用 Invoke 会失败,因为 CLR 不允许执行未闭合的泛型签名。
必须用 MakeGenericMethod 显式指定类型参数:
var list = new List<string>();
var method = typeof(List<string>).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,很容易因隐式类型丢失崩掉。








