zoukankan      html  css  js  c++  java
  • C# 反射(Reflection)

    什么是反射

    发射是 .net framework 提供的一个帮助类库,用于读取和使用元数据。

    用到的类:System.Reflection,System.Type。System.Type 类对于反射起着核心的作用。 当反射请求加载的类型时,公共语言运行时将为它创建一个 Type。 您可以使用 Type 对象的方法、字段、属性和嵌套类来查找有关该类型的所有信息。

    反射优缺点

    优点:

    • 1、反射提高了程序的灵活性和扩展性。
    • 2、降低耦合性,提高自适应能力。
    • 3、它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

    缺点:

    • 1、性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
    • 2、使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因而会带来维护的问题,反射代码比相应的直接代码更复杂。

    反射的用途

    • 1、它允许在运行时查看特性(attribute)信息。
    • 2、它允许审查集合中的各种类型,以及实例化这些类型。
    • 3、它允许延迟绑定的方法和属性(property)。
    • 4、它允许在运行时创建新类型,然后使用这些类型执行一些任务。
    • 5、MVC的路由就是反射做的。访问的Global的时候,会加载一遍dll

    查看元数据

    1、获取当前实例的 System.Type 的两种方式

    //使用对象 GetType()方法
    Rectangle nc = new Rectangle();
    Type type = nc.GetType();
                
    //使用 C# typeof 运算符
    Type type = typeof(Rectangle);

    2、查看类中的成员

    MemberInfo[] minfos = type.GetMembers();
    foreach (var i in minfos)
    {
        Console.WriteLine("成员: {0}", i.Name);
    }

    3、查看类中的构造方法

    ConstructorInfo[] ci = type.GetConstructors();
    foreach (var i in ci)
    {
        Console.WriteLine("构造函数: {0}", i.Name);
    }

    4、查看类中的属性

    PropertyInfo[] pis = type.GetProperties();
    foreach (var i in pis)
    {
        Console.WriteLine("属性: {0}", i.Name);
    }

    5、查看类中的字段

    FieldInfo[] fis = type.GetFields();
    foreach (var i in fis)
    {
        Console.WriteLine("字段: {0}", i.Name);
    }

    6、用反射生成对象,并调用属性、方法和字段进行操作

    object obj = Activator.CreateInstance(type);// 创建实例
    FieldInfo fi = type.GetField("hight");// 取得hight字段 
    fi.SetValue(obj, 5);// 给hight字段赋值 
    PropertyInfo pi1 = type.GetProperty("length");// 取得length属性 
    pi1.SetValue(obj, 10, null);// 给length属性赋值
    PropertyInfo pi2 = type.GetProperty("width");// 取得width属性 
    pi2.SetValue(obj, 20, null);// 给width属性赋值 
    MethodInfo mi = type.GetMethod("GetVolume");// 取得GetVolume方法 
    mi.Invoke(obj, null);// 调用GetVolume方法

    7、查看类中的特性、

    Object[] attributes = type.GetCustomAttributes(false);
    foreach (var i in attributes)
    {
        DeBugInfo dbi = i as DeBugInfo;
        if (null != dbi)
        {
            Console.WriteLine("Bug no: {0}, Message: {1}", dbi.BugNo, dbi.Message);
        }
    }

    8、完整代码

    using System;
    using System.Reflection;
    namespace ConsoleTest
    {
        // 一个自定义特性 BugFix 被赋给类及其成员
        [AttributeUsage(AttributeTargets.Class |
        AttributeTargets.Constructor |
        AttributeTargets.Field |
        AttributeTargets.Method |
        AttributeTargets.Property,
        AllowMultiple = true)]
    
        public class DeBugInfo : System.Attribute
        {
            private int bugNo;
            public string message;
    
            public DeBugInfo(int bg)
            {
                this.bugNo = bg;
            }
    
            public int BugNo
            {
                get
                {
                    return bugNo;
                }
            }
            public string Message
            {
                get
                {
                    return message;
                }
                set
                {
                    message = value;
                }
            }
        }
        /// <summary>
        /// 矩形
        /// </summary>
        [DeBugInfo(45, Message = "Return type mismatch")]
        [DeBugInfo(49, Message = "Unused variable")]
        public class Rectangle
        {
            public int hight = 0;
            public double length { get; set; }
            public double width { get; set; }
            public Rectangle()
            {
            }
            public Rectangle(double l, double w)
            {
                length = l;
                width = w;
            }
            // 计算面积
            [DeBugInfo(55, Message = "Return type mismatch")]
            public void GetArea()
            {
                Console.WriteLine("面积: {0}", length * width);
            }
            //计算体积
            [DeBugInfo(56)]
            public void GetVolume()
            {
                Console.WriteLine("体积: {0}", length * width * hight);
            }
        }
    
        class ExecuteRectangle
        {
            public static void Main12()
            {
                //使用对象GetType()方法
                //Rectangle nc = new Rectangle();
                //Type type = nc.GetType();
                
                //使用 C# typeof 运算符
                Type type = typeof(Rectangle);
    
                // 获取 Rectangle 类的所有成员
                Console.WriteLine("
    遍历 Rectangle 类的成员开始---------------");
                MemberInfo[] minfos = type.GetMembers();
                foreach (var i in minfos)
                {
                    Console.WriteLine("成员: {0}", i.Name);
                }
                Console.WriteLine("-------------------结束-------------------");
    
                // 获取 Rectangle 类的所有构造函数
                Console.WriteLine("
    遍历 Rectangle 类的构造函数开始-----------");
                ConstructorInfo[] ci = type.GetConstructors();
                foreach (var i in ci)
                {
                    Console.WriteLine("构造函数: {0}", i.Name);
                }
                Console.WriteLine("-------------------结束-------------------");
    
                // 获取 Rectangle 类的所有属性
                Console.WriteLine("
    遍历 Rectangle 类的属性开始---------------");
                PropertyInfo[] pis = type.GetProperties();
                foreach (var i in pis)
                {
                    Console.WriteLine("属性: {0}", i.Name);
                }
                Console.WriteLine("-------------------结束-------------------");
    
                // 获取 Rectangle 类的所有public字段
                Console.WriteLine("
    遍历 Rectangle 类的字段开始---------------");
                FieldInfo[] fis = type.GetFields();
                foreach (var i in fis)
                {
                    Console.WriteLine("字段: {0}", i.Name);
                }
                Console.WriteLine("-------------------结束-------------------");
    
                //用反射生成对象,并调用属性、方法和字段进行操作
                Console.WriteLine("
    用反射生成对象,并调用属性、方法和字段进行操作");
                object obj = Activator.CreateInstance(type);// 创建实例
                FieldInfo fi = type.GetField("hight");// 取得hight字段 
                fi.SetValue(obj, 5);// 给hight字段赋值 
                PropertyInfo pi1 = type.GetProperty("length");// 取得length属性 
                pi1.SetValue(obj, 10, null);// 给length属性赋值
                PropertyInfo pi2 = type.GetProperty("width");// 取得width属性 
                pi2.SetValue(obj, 20, null);// 给width属性赋值 
                MethodInfo mi = type.GetMethod("GetVolume");// 取得GetVolume方法 
                mi.Invoke(obj, null);// 调用GetVolume方法
                Console.WriteLine("-------------------结束-------------------");
    
                // 遍历 Rectangle 类的特性
                Console.WriteLine("
    遍历 Rectangle 类的特性开始---------------");
                Object[] attributes = type.GetCustomAttributes(false);
                foreach (var i in attributes)
                {
                    DeBugInfo dbi = i as DeBugInfo;
                    if (null != dbi)
                    {
                        Console.WriteLine("Bug no: {0}, Message: {1}", dbi.BugNo, dbi.Message);
                    }
                }
                Console.WriteLine("-------------------结束-------------------");
    
                // 遍历 Rectangle 类的方法上的特性(此处只遍历)
                Console.WriteLine("
    遍历 Rectangle 类的方法上的特性开始-------");
                MethodInfo[] m = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
                foreach (var i in m )
                {
                    foreach (Attribute a in i.GetCustomAttributes(true))
                    {
                        DeBugInfo dbi = a as DeBugInfo;
                        if (null != dbi)
                        {
                            Console.WriteLine("Bug no: {0}, for Method: {1}, Message: {2}", dbi.BugNo, i.Name, dbi.Message);
                        }
                    }
                }
                Console.WriteLine("-------------------结束-------------------");
    
                Console.ReadLine();
            }
        }
    }
    
    反射的完整代码
    反射的完整代码

    运行结果:

    System.Reflection.Assembly类

    Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。

    使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化。

    //通过程序集名称返回Assembly对象
    Assembly ass = Assembly.Load("ConsoleTest");
    
    //通过DLL、EXE文件名称返回Assembly对象
    Assembly ass = Assembly.LoadFrom("ConsoleTest.exe");
    
    //通过Assembly获取程序集中类
    Type t = ass.GetType("ConsoleTest.Rectangle");   //参数必须是类的全名
    
    //通过Assembly获取程序集中所有的类
    Type[] types = ass.GetTypes();

    相关文章:http://www.runoob.com/csharp/csharp-reflection.html  

                  https://www.cnblogs.com/Kare/p/4601436.html  

                  http://www.cnblogs.com/yaozhenfa/p/CSharp_Reflection_1.html#3826975

  • 相关阅读:
    壶公随感
    消息称微软受谷歌刺激 急于收购雅虎(zz)
    远程注销Windows用户
    "杀人"游戏中的一些规律
    由两点的经纬度估算距离
    我的城市?
    Blog里的一个bug,dudu看能否修正?
    这两天真烦
    发简历,找上海.Net方面软件开发工作
    "上海.NET俱乐部"聚会筹备进展
  • 原文地址:https://www.cnblogs.com/cang12138/p/8191994.html
Copyright © 2011-2022 走看看