運行時改變私有的只讀字段,靜態字段值

如果一個類定義了一個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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章