必须显式指定 bindingflags.nonpublic 才能获取私有方法,否则返回 null;调用私有实例方法需传入有效实例对象,不能为 null;aot 编译下反射调用私有成员可能被裁剪或禁止。

用 GetMethod 获取私有方法必须显式指定 BindingFlags
反射默认只返回 public 成员,想拿到 private 方法,不加标志位会直接返回 null,而不是报错——这容易让人误以为方法名写错了。
正确做法是组合使用 BindingFlags.NonPublic | BindingFlags.Instance(实例方法)或 BindingFlags.Static(静态方法):
var method = typeof(MyClass).GetMethod("DoWork",
BindingFlags.NonPublic | BindingFlags.Instance);
- 漏掉
BindingFlags.NonPublic→ 返回null,调用时抛NullReferenceException - 该方法是静态的却用了
Instance→ 找不到,同样返回null - 方法重载存在时,仅靠名称不够,得用
GetMethods()过滤参数类型,或传入Type[]参数数组匹配
调用私有实例方法前必须传入目标对象实例
MethodInfo.Invoke 对私有实例方法的要求和 public 方法完全一致:第一个参数不能为 null,必须是有效的类实例。哪怕方法逻辑上没用到 this,反射层仍强制校验。
常见错误是直接传 null 试图“静态调用”私有实例方法:
method.Invoke(null, new object[] { "arg" }); // ❌ 抛 TargetException
- 正确方式:
method.Invoke(instance, args),其中instance是已创建的MyClass对象 - 如果类没有公开构造函数,需用
Activator.CreateInstance(type, BindingFlags.NonPublic | BindingFlags.Instance, null, null, null)创建实例 - 注意:私有构造函数 + 密封类 + 无 public 工厂方法时,可能根本无法获得合法实例
私有方法里访问 this 字段或调用其他私有成员不会自动“穿透”
反射调用私有方法本身只是绕过了编译器检查,运行时仍是正常执行上下文。方法内部若访问 private 字段、调用 private 方法,只要当前实例状态合法,一切照常;但若该方法依赖某些未初始化的私有状态(比如只在 public 构造流程中设置的 _isInitialized),就会出逻辑错误,而非访问异常。
- 这不是反射的限制,而是设计契约被跳过导致的状态不一致
- 调试时看到
NullReferenceException在私有方法内部抛出?先检查它依赖的私有字段是否真有值,别急着怀疑反射调用本身 - 单元测试中滥用反射调用私有方法,容易掩盖“本不该暴露的依赖”,后续重构时更难发现断裂点
.NET Core / .NET 5+ 中 ReflectionContext 和 AOT 兼容性问题
在启用 AOT 编译(如 .NET 7+ 的 NativeAOT)或某些受限制的运行环境(如 iOS、Blazor WebAssembly)中,动态反射调用私有成员可能被裁剪或禁止,GetMethod 返回 null 或运行时报 NotSupportedException。
- 不是所有
private方法都能被 AOT 保留——需用[UnconditionalSuppressMessage]或[DynamicDependency]显式标注 - 发布时开启
TrimMode=link且未配置保留规则,私有方法大概率被移除 - 替代思路:把关键逻辑抽成
internal并配合[InternalsVisibleTo],比硬啃反射更可控
真正麻烦的从来不是“怎么调用”,而是调用之后它到底有没有按你想象的方式跑完——尤其是当私有方法悄悄改了依赖顺序,或者换了个初始化路径。










