zoukankan      html  css  js  c++  java
  • 反射

    反射

    定义 :查看和操作元数据的操作 ;

    原理: 利用元数据(包括) ,获取类型的完整描述'

    特点: 可以获取类型所有的成员和方法,无论他们是否是private,甚至还可以修改值,调用私有静态构造函数。
    动态加载(也叫晚期绑定);

    使用套路

      class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person();
                Type type = p.GetType();
    
                //反射可以获取并调用私有方法
                var set_NameMethod = type.GetMethod("set_Name", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
                set_NameMethod.Invoke(p, new object[] { "aaa" });
    
                //当方法带有参数时,需要按顺序传递参数的类型
                var setNickNameMethod = type.GetMethod("SetNickName", new Type[] { typeof(string), typeof(string) });
                setNickNameMethod.Invoke(p, new object[] { "xxx", "jack" });
    
                //方法二,使用InvokeMember 调用方法不常用; Binder参数不能传Null
                // type.InvokeMember("SetNickName", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic, null, p, new object[] { "xxx", "jim" });
    
                //调用泛型方法 ,必须要调用  MakeGenericMethod(type)
                var genericMethod = type.GetMethod("SetTemperament");
                var intSetTemperament = genericMethod.MakeGenericMethod(typeof(int));
                intSetTemperament.Invoke(p, new object[] { 100 });
    
                var strSetTemperament = genericMethod.MakeGenericMethod(typeof(string));
                strSetTemperament.Invoke(p, new object[] { "Nice" });
    
                //读写实例字段
                var field_NickName = type.GetField("_NickName", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
                field_NickName.GetValue(p);
                field_NickName.SetValue(p, "jack");
    
                //读写静态字段,当是静态字段时,obj参数的值可以传 p 或者 null
                var field_MaxAge = type.GetField("_MaxAge", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
                field_MaxAge.GetValue(null);
                field_MaxAge.SetValue(null, 500);
    
            }
        }
    
        public class Person
        {
            public string Name { get; private set; }
            private string _NickName = "xxx";
            public static int _MaxAge;
    
            static Person() { _MaxAge = 200; }
    
            public void PrintName() { Console.WriteLine(Name); }
    
            public void SetNickName(string oldName, string newName)
            {
                if (oldName != _NickName)
                {
                    Console.WriteLine("旧的 _NickName 不正确"); return;
                }
                _NickName = newName;
            }
    
            public object _Temperament;
            public void SetTemperament<T>(T temperament)
            {
                Console.WriteLine($"temperament Type:{temperament.GetType()}");
                _Temperament = temperament;
            }
        }
    

    关于 BingingFlags 常用的值

    名称 说明
    Instance 指定实例成员要包括在搜索中。
    Static 指定静态成员要包括在搜索中
    NonPublic 指定非公共成员要包括在搜索中。
    DeclaredOnly 指定只应考虑在所提供类型的层次结构级别上声明的成员。 不考虑继承的成员。

    常用方法:

    方法名称 说明
    GetMembers() 返回为当前 Type 的所有公共成员
    GetMethods() 返回为当前 Type 的所有公共方法。
    GetProperties() 返回为当前 Type 的所有公共属性。
    GetFields() 返回当前 Type 的所有公共字段。
    GetConstructors() 返回为当前 Type 定义的所有公共构造函数。

    上面的几个方法 ,都有对应的 MethodName(BindingFlags) 重载版本

    性能:
    反射调用时比较慢,由于要进行参数校验,和类型对比;大概是直接调用的100倍;

    大多数情况下性能:直接调用>委托调用>Emit调用>表达式调用>反射调用>反射后调用DynamicInvoke 。

    优化的方法是通过创建代理 ,然后 代理对象.Invoke ,注意是使用delegate.Invoke,而不是delegate.DynamicInvoke;
    但是需要创建代理,通用的方案是结合泛型
    通过表达式创建委托

  • 相关阅读:
    RN-Android构建失败:Caused by: org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'AwesomeProject'.
    Android更新包下载成功后不出现安装界面
    真机调试: The application could not be installed: INSTALL_FAILED_TEST_ONLY
    react native 屏幕尺寸转换
    Android Studio生成签名文件,自动签名,以及获取SHA1和MD5值
    React Native安卓真机调试
    git提交代码报错Permission denied, please try again
    The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
    命令行设置快捷命令
    Linux 常用指令
  • 原文地址:https://www.cnblogs.com/francisXu/p/13741025.html
Copyright © 2011-2022 走看看