现在的位置: 首页 > 综合 > 正文

运行时改变私有的只读字段,静态字段值

2013年04月14日 ⁄ 综合 ⁄ 共 2062字 ⁄ 字号 评论关闭

如果一个类定义了一个Private的字段,在运行时,正常方式下,在类的外部当然是不能访问这个字段,更谈不上改变值了。但在特殊情况下,我们不能修改已有类的代码,但又要去改变,怎么办?用反射。代码是最好的表达语言:

 

       /* 先定义一个测试类 */

    public class TestClass {

        private readonly int i1 = 10;

        private const int i2 = 20;

        private int i3 = 30;

        private static int i4 = 40;

        private static readonly int i5 = 50;

 

        public void Print() {

            Console.WriteLine("i1: " + i1.ToString());

            Console.WriteLine("i2: " + i2.ToString());

            Console.WriteLine("i3: " + i3.ToString());

            Console.WriteLine("i4: " + TestClass.i4.ToString());

            Console.WriteLine("i5: " + TestClass.i5.ToString());

            Console.WriteLine();

        }

    }

 

 

   /* 反射方法修改类的私有字段值 */

    class Program {

        static void Main(string[] args) {

 

            TestClass tc = new TestClass();

            Type type = typeof(TestClass);

            tc.Print();           

 

            // 只读字段,可通过反射方式修改值

            FieldInfo fi = type.GetField("i1", BindingFlags.NonPublic | BindingFlags.Instance);

            fi.SetValue(tc, (int)fi.GetValue(tc) + 1);

 

            // 常量字段,反射也无法修改,如果取消下面语句的注释,执行会出错。

            /* 原因说明:常量的值必须在编译时就确定(只能是基元类型),也就是说在定义时就赋值。

               编译后常量的值是保存在程序集的元数据中,在运行时是不可修改的;

               而其它字段是存储在动态内存中,在运行时是可修改的。*/

            fi = type.GetField("i2", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);

            //fi.SetValue(null, (int)fi.GetValue(null) + 1);

 

            // 正常字段,当然可以修改

            fi = type.GetField("i3", BindingFlags.NonPublic | BindingFlags.Instance);

            fi.SetValue(tc, (int)fi.GetValue(tc) + 1);

 

            // 静态字段,也可修改

            fi = type.GetField("i4", BindingFlags.NonPublic | BindingFlags.Static);

            fi.SetValue(null, (int)fi.GetValue(null) + 1);

 

            // 静态只读字段,下面代码不出错,改变了反射字段的值,但类中的字段值并没有被改变

            fi = type.GetField("i5", BindingFlags.NonPublic | BindingFlags.Static);

            fi.SetValue(null, (int)fi.GetValue(null) + 1);

           

            int i5 = (int)fi.GetValue(null); // i5 得到值为 51

 

            tc.Print();

            Console.WriteLine("i5: " + i5.ToString());

            Console.ReadKey();

         }

    }

 

 

 

下面是输出结果:

i1:10

i2:20

i3:30

i4:40

i5:50

 

i1:11

i2:20

i3:31

i4:41

i5:50

 

i5:51

 

抱歉!评论已关闭.