zoukankan      html  css  js  c++  java
  • .Net反射机制

    现在谈.Net反射机制本不在计划中,因为本打算研究完设计模式后再去学习别的技术;但迫于设计模式系列一创建型之(抽象工厂模式)一章中遗留问题,才不得已在设计模式之游中插入本篇文章!签于本人对反射理解也不够深入,这里也只做些简单介绍,详见MSDN;大牛们无须光顾!

      


    1、反射简介

    • 概念:

          .Net 中Reflection翻译为“反射”,是.Net中获取运行时类型信息的一种方式。.Net的应用程序由几个部分:程序集(Assembly)、模块(Module)、类型 (class)组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息。

    • 作用:
      1. Assembly类可以获得正在运行的装配件信息
      2. 可以动态的加载装配件
      3. 在装配件中查找类型信息
      4. 创建该类型的实例

    第一次看到这样的词相信你也会不知所以然!一个很通俗的东东,一旦用专业术语表述就像很高雅。从字面意思根本无法明白它在.Net中是什么?通俗的讲,在形成最终的.exe或.dll之前,那些不相关的和相关的东西(比如说很多类)要打成包组装在一起,这些东西就叫做装配件。我们直接把它理解为exe和dll就可以了。 

      

    2、反射应用 

    1. Type类于获取类型信息

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

    以下所有均以设计模式系列一创建型之(抽象工厂模式)章节中为例:

          static void Main(string[] args)
            {
                ChinaFactory factory = new ChinaFactory();
                Type type = factory.GetType();
                Console.WriteLine(
                        "类型名:" + type.Name
                        + "
    类全名:" + type.FullName
                        + "
    命名空间名:" + type.Namespace
                        + "
    程序集名:" + type.Assembly
                        + "
    模块wei名:" + type.Module
                        + "
    基类名:" + type.BaseType
                        + "
    是否为类:" + type.IsClass
                    );
                Console.ReadLine();
            }

    运行结果:

      2.获取程序集元数据

      Assembly类定义了一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行库应用程序构造块。因为程序集中是使用元数据进行自我描述的,所以我们就能通过其元数据得到程序集内部的构成。结合Assembly和反射能够获取程序集的元数据,但是首先要将程序集装入内存中。可以使用Assembly类的多种静态Load方法加载程序集。

                //获取当前执行代码的程序集
                Assembly assem = Assembly.GetExecutingAssembly();
                Console.WriteLine("程序集全名:" + assem.FullName);
                Console.WriteLine("程序集的版本:" + assem.GetName().Version);
                Console.WriteLine("程序集初始位置:" + assem.CodeBase);
                Console.WriteLine("程序集位置:" + assem.Location);
                Console.WriteLine("程序集入口:" + assem.EntryPoint);
                Type[] types = assem.GetTypes();
                Console.WriteLine("程序集下包含的类型:");
                foreach (var item in types)
                {
                    Console.WriteLine("类:" + item.Name);
                }
    
                Console.ReadLine();    
    View Code

    运行结果:

      

      3.动态加载类型

      早绑定是在编译时绑定对象类型,而晚绑定是在运行时才绑定对象的类型。利用反射可以实现晚绑定,即动态加载类型,并调用他们的方法。听着挺神奇的,下面让我们爽一把:

                //获取当前执行代码的程序集
                Assembly assem = Assembly.GetExecutingAssembly();
                //从程序集中创建一个ChinaFactory实例并且用object类型的引用obj指向它
                object obj = assem.CreateInstance("抽象工厂模式.ChinaFactory", false);
                MethodInfo m = assem.GetType("抽象工厂模式.ChinaFactory").GetMethod("CreateBonus");
                object objRet = m.Invoke(obj, null);
                Console.WriteLine("CreateBonus returned {0}.", objRet);
                //CreateBonus 返回IBonus类型
                IBonus bonus = m.Invoke(obj, null) as IBonus;
                Console.WriteLine(bonus.Calculate());
    
                Console.ReadLine();

    运行结果:

    果真是强大!Ok,体验了一把也对反射有了一些简单的认知,下面就开始解决遗留的问题:如何解决抽象工厂中判断分支问题?

    3、解决遗留问题 

    其实应用反射很简单:

        /// <summary>
        /// AbstractFactory
        /// </summary>
        public abstract class AbstractFactory
        {
            public static AbstractFactory GetInstance()
            {
                string factoryName = ConfigurationManager.AppSettings["factoryName"];
                AbstractFactory instance;
                if (!string.IsNullOrEmpty(factoryName))
                {
                    Assembly ass = Assembly.GetExecutingAssembly();
                    //动态创建类型
                    instance = (AbstractFactory)ass.CreateInstance("抽象工厂模式." + factoryName);
                }
                else
                {
                    instance = null;
                }
                return instance;
            }
            public abstract IBonus CreateBonus();
            public abstract ITax CreateTax();
        }
    View Code

    这样看上去舒服多了,无论代码怎么变迁,我们只需要修改配置文件就Ok!


    4、总结

    以上只是反射的基本应用,其真正的实现原理还需继续深入探讨!

  • 相关阅读:
    |,&,<<,>>运算符
    Unity 异步加载场景
    string字母排序,
    冒泡算法
    Direct3D 12 编程---(1)
    点云密度粗估计
    git工具使用
    opencv---灰度图像与彩色图像遍历
    求平面两直线的交点,两直线段的交点
    结构体重载运算符
  • 原文地址:https://www.cnblogs.com/tianboblog/p/3981749.html
Copyright © 2011-2022 走看看