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。

  • 相关阅读:
    chrome 浏览器与chromedriver 对应关系以及 对应的驱动下载
    pip 安装six 报错 ModuleNotFoundError: No module named 'pip._internal.cli.main'
    django 连接远程mysql 报错 django.db.utils.OperationalError: (1045, "Access denied for user 'root'@'localhost' (using password: NO)")
    MySQL8.0允许外部访问
    Linux 安装mysql
    php导出导入excel插件
    解决php导出csv文件utf8中文乱码问题
    Docker 安装mysql5.6
    centos7 设置静态IP
    U盘制作centos7系统并安装
  • 原文地址:https://www.cnblogs.com/quark/p/2088150.html
Copyright © 2011-2022 走看看