• 关于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。

  • 相关阅读:
    iOS 自动化测试踩坑(二):Appium 架构原理、环境命令、定位方式
    干货 | 掌握 Selenium 元素定位,解决 Web 自动化测试痛点
    代理技术哪家强?接口 Mock 测试首选 Charles
    浅谈MVC缓存
    PetaPoco 快速上手
    解释器模式(26)
    享元模式(25)
    中介者模式(24)
    职责链模式(23)
    命令模式(22)
  • 原文地址:https://www.cnblogs.com/quark/p/2088150.html
Copyright © 2020-2023  润新知