如何使用反射在C#中更改静态只读字段的值?

7
在fieldInfo类中,SetFields方法的第一个参数需要传递对象。在C#中,有没有一种使用反射修改静态只读字段的方法?
到目前为止,我已经...
var field = typeof(ClassName).GetField("FieldName",BindingFlags.Instance|BindingFlags.NonPublic);

3
为什么你想那样做?如果这是你的代码,请不要将其声明为“static readonly”。如果不是你的代码,这样做可能会破坏某些东西。 - Richard
2
@Richard 虽然这是正确的,但有时候你确实想要能够“不正确地”搞事情。此外,如果kunj2aan不尝试绕过系统,他会成为什么样的黑客呢? - Chris Pfohl
例如类似的问题 我能否使用反射在C#中更改私有只读字段? - Michael Freidgeim
2个回答

10

如果您想获取一个静态字段,应该使用BindingFlags.Static而不是BindingFlags.Instance,因为后者用于实例字段。

然后可以使用field.SetValue(null, newValue)来设置值。请注意,可以将null作为目标参数传递,因为不需要对象实例。假设您拥有足够的权限,反射将愉快地更改只读字段的值。


1
我遇到了一个有趣的情况,field.GetValue(null) 返回新值,但是直接访问字段(例如 Trace.WriteLine(FieldName))返回旧值。 - Emperor Orionii
1
Greg,你试过这个吗?因为我得到了不同的结果。我可以通过这种方式设置只读实例字段,但不能设置只读静态字段。 - smartcaveman
1
它可能在两年前我尝试的运行时版本上正常工作。但显然你不应该这样做,这违反了你与运行时的合同,并且任何运行时的更新都可能导致它停止工作。我猜他们已经这样做了! - Greg Beech
我在调试时遇到了这个问题。调试器显示了更新后的值,但程序继续使用旧值。也许这与JIT有关。 - AlexDev
2
@AlexDev:JIT 将尝试优化只读值,将其直接编码到汇编语言中(charint 等),因此在您的方法首次调用时字段的值将保持应用程序生命周期的其余部分。请参见此 - StriplingWarrior

5
你离正确很近了,但是你的BindingFlag是错误的。Instance指的是实例字段,而你应该使用BindingFlags.Static
var field = typeof(ClassName).GetField("FieldName",BindingFlags.Static|BindingFlags.NonPublic);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接