zoukankan      html  css  js  c++  java
  • 关于System.Relection.FieldInfo的几点使用心得

    在工作当中,经常会用到反射技术来实现对一些对象的序列化\反序列化的功能。

    以下是对于FieldInfo这个类型的两点心得:

    假设有如下结构

        public struct SomeStruct
        {
            public int publicField;
            private int privateField;
            public static int staticField;
        }

    一、使用BindingFlags获取一个类或者结构特定的字段

    以下是一段测试代码:

            private static void TestGetFields()
            {
                Action<IEnumerable<FieldInfo>> display = (e) =>
                {
                    foreach (var item in e)
                    {
                        Console.WriteLine(item.Name);
                    }
                };   // display fields
    
                SomeStruct ss = new SomeStruct();
    
                Console.WriteLine("BindingFlags.Instance | BindingFlags.Public");
                var fields = ss.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
                display(fields);
    
                Console.WriteLine("BindingFlags.Static | BindingFlags.Public");
                fields = ss.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
                display(fields);
    
                Console.WriteLine("BindingFlags.Instance | BindingFlags.NonPublic");
                fields = ss.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
                display(fields);
            }

    得到的结果如下:

    image

    以上结果似乎在意料当中,但是有一点需要注意的是,在设定BingdingFlags的时候,必须使用BingFlags.Instande或者BindingFlags.Static,否则GetFields方法将返回一个空集合。

      

    二、结构对象使用FieldInfo.SetValue方法

    对一个结构使用SetValue方法是需要小心的。

    FieldInfo.SetValue方法的函数签名如下:

    public void SetValue(object obj, object value);

    看下面的两个方法:

            private static void FieldInfo_SetValue1()
            {
                SomeStruct ss = new SomeStruct();
                FieldInfo fieldInfo = ss.GetType().GetField("publicField");
                fieldInfo.SetValue(ss, 20);
                Console.WriteLine(ss.publicField);   // result is 0;
            }
    
            private static void FieldInfo_SetValue2()
            {
                SomeStruct ss = new SomeStruct();
                object obj = ss as object;   // boxing ss;
                FieldInfo fieldInfo = ss.GetType().GetField("publicField");
                fieldInfo.SetValue(obj, 20);
                ss = (SomeStruct)obj;    // unboxing ss;
    
                Console.WriteLine(ss.publicField);   // result is 20;
            }

    我们知道第一种方法会有问题,原因就在于调用SetValue方法的时候,由于结构对象是值类型,因此会临时被装箱,造成实际修改的字段不是ss的字段;第二种方法就是先装箱,得到一个对于ss备份的引用,然后修改完成后在拆箱赋值给ss。

  • 相关阅读:
    HDU_1846 Brave Game(sg函数简化版)
    POJ 3225 Help with Intervals(线段树)
    ZOJ_3501 Roman Order
    HDU_1527 取石子游戏(威佐夫博弈)
    HDU_2112 HDU Today(DIjkstra + map映射)
    HDU_3339 In Action(Dijkstra + DP)
    单链表的实现(课本上的算法)
    haproxy 基于 uri 实现调度
    haproxy 基于 cookie 实现 session 绑定
    [转]ASP.NET 虚拟主机安全漏洞解决方案
  • 原文地址:https://www.cnblogs.com/quark/p/2088150.html
Copyright © 2011-2022 走看看