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;
    但是需要创建代理,通用的方案是结合泛型
    通过表达式创建委托

  • 相关阅读:
    Bitnami 2015
    knowledgeroot
    远程管理服务 Windows Remote Management (WS-Management)
    Composer 安装
    开源知识库管理系统选型 centos6.4 搭建knowlededgeroot-1.0.4知识库平台
    两个IP实现IIS和Apache公用80端口的设置方法
    Solidworks工程图如何使用,替换图纸格式模板文件
    Solidworks工程图 如何绘制向视图,辅助视图
    Solidworks打印工程图超出范围了怎么办
    Solidworks 如何绘制投影曲线
  • 原文地址:https://www.cnblogs.com/francisXu/p/13741025.html
Copyright © 2011-2022 走看看