propertyinfo.setvalue 和 getvalue 需严格检查 canwrite、实例非空、bindingflags 匹配及类型兼容性,否则易触发 targetexception、nullreferenceexception 或静默失败。

PropertyInfo.GetValue 和 SetValue 不是“调用就能用”的工具,跳过可写性检查、实例空值、BindingFlags 组合或类型兼容性,90% 的崩溃和静默失败都源于这四点。
PropertyInfo.SetValue 前必须检查 CanWrite
直接调用 SetValue 却没查 CanWrite,大概率触发 TargetException 或看似成功却没生效——尤其面对 get; init; 属性(.NET 5+ 中运行时不可写)、只读自动属性、或带访问控制逻辑的 setter。
-
CanWrite返回false时,SetValue必然失败,别指望反射绕过语言规则 -
init属性不能后期修改:必须通过构造函数或Activator.CreateInstance传参初始化,反射设值会抛NotSupportedException - 若真需强制写 private set 属性,应单独获取其 setter 方法(
GetProperty(...).GetSetMethod(true)),再Invoke;但这是权宜之计,不推荐进业务主干
GetValue 报 NullReferenceException 或 TargetException?先看实例和 BindingFlags
GetValue 崩在 NullReferenceException,八成是传了 null 实例给实例属性;崩在 TargetException,往往是 BindingFlags 没配对,或对象类型与 PropertyInfo.DeclaringType 不匹配。
- 实例属性:必须传非
null对象,且类型要与PropertyInfo.DeclaringType一致(子类实例可,但基类PropertyInfo+ 子类实例可能触发 “Object does not match target type”) - 静态属性:第一个参数必须传
null,否则报错 - 默认
GetProperty("Name")只找public实例属性;读private属性得加BindingFlags.NonPublic | BindingFlags.Instance;漏掉Instance就只扫静态成员 - 跨程序集读
internal属性?确认对方打了[InternalsVisibleTo("YourAssemblyName")]
值类型、null 和类型转换最容易踩坑
给 int 属性赋 null,或把 int? 的 null 往非空 int 上塞,会立刻炸出 ArgumentException: "Object of type 'null' cannot be converted to type 'System.Int32'"。
- 判断是否可空:
Nullable.GetUnderlyingType(propertyInfo.PropertyType) != null - 非空值类型属性,禁止传
null;来源不确定时,用Convert.ChangeType(value, propertyInfo.PropertyType)转换,比value as T或直接 cast 更安全 - 对
struct实例调用GetValue,返回的是装箱后的object,不是引用,别误以为能原地改字段
批量操作或高频调用时,缓存 PropertyInfo 是刚需
每次 type.GetProperty("X") + prop.SetValue(obj, v) 都有明显开销。1000 个对象循环设 5 个属性,没缓存可能慢 3–5 倍。
- 缓存键建议用
(Type, propertyName, BindingFlags)元组,注意泛型类型(如List<int></int>和List<string></string>)要区分 - 更进一步:用
Expression.Lambda编译成委托,GetValue/SetValue可提速 10x+,但首次编译有成本,适合稳定结构的长期运行场景 - 调试时建议日志输出
type.GetProperties(flags)结果,确认目标属性是否真被发现——很多“设不上值”只是名字拼错或大小写不符
真正难的不是写对一行 SetValue,而是想清楚:这个属性到底归谁声明、能不能写、值从哪来、对象是不是活的、要不要跨程序集、会不会被 JIT 优化掉。这些细节藏在 DeclaringType、CanWrite、BindingFlags 和空值检查里,漏一个就掉坑。










