仅持有System.Object类型的反射属性值,如何修改对应属性?
能不能修改原对象的属性值?
答案是不行——核心原因是你缺少了最关键的东西:原Painting对象的实例引用。你手里的clr只是原属性值的「副本」(值类型场景)或者「指向原属性对象的引用」(引用类型场景),但没有原对象的话,你根本没法把修改后的结果同步回原对象的属性里。
分两种场景详细说明:
1. 属性是值类型(比如System.Color)
System.Color属于值类型,当你调用GetValue时,返回的是它的装箱副本。你拿到的clr只是这个副本的装箱形式,哪怕你拆箱修改它,也完全不会影响原Painting对象的PaintingColor属性。而且因为你没有原对象pnt,连调用SetValue把新值塞回去的机会都没有。
举个代码例子:
// 假设你的Painting类定义 public class Painting { public Color PaintingColor { get; set; } } // 你当前的状态 object clr = pnt.GetType().GetProperty("PaintingColor").GetValue(pnt); // 拿到的是Color的装箱副本 // 尝试修改本地副本 Color tempColor = (Color)clr; tempColor = Color.Red; // 这一步完全没用!原pnt的PaintingColor还是原来的颜色,因为你修改的只是本地副本,而且没有原对象来执行SetValue
2. 属性是引用类型
如果属性是引用类型(比如自定义的ColorWrapper类),你拿到的clr是指向原属性对象的引用。这时候你可以修改该对象的内部成员,比如修改它的R/G/B值,这会影响原Painting对象里属性指向的那个对象。但如果你想把属性本身替换成一个新的对象实例,还是做不到——因为你没有原对象,没法调用SetValue来替换属性的引用。
代码示例:
// 自定义引用类型 public class ColorWrapper { public byte R { get; set; } public byte G { get; set; } public byte B { get; set; } } // Painting类 public class Painting { public ColorWrapper PaintingColor { get; set; } } // 你当前的状态 object clr = pnt.GetType().GetProperty("PaintingColor").GetValue(pnt); // 拿到的是ColorWrapper的引用 // 可以修改内部成员,这会影响原对象的属性指向的实例 ColorWrapper wrapper = (ColorWrapper)clr; wrapper.R = 255; // 原pnt的PaintingColor.R现在变成255了 // 但没法替换整个属性引用 wrapper = new ColorWrapper { R=0, G=0, B=0 }; // 这只是修改了本地变量wrapper的引用,原pnt的PaintingColor还是指向原来的实例,你没有原对象来调用SetValue
总结
要修改原对象的属性值,必须同时拥有两个关键要素:
- 原对象的实例引用(也就是你没有的
pnt) - 该属性的
PropertyInfo对象
然后通过propertyInfo.SetValue(原对象, 新值)来完成修改。你现在只有属性值的副本/引用,没有原对象,所以根本无法修改原对象的该属性本身。
内容的提问来源于stack exchange,提问作者YogoWafel
相关产品推荐
相关产品推荐

