zoukankan      html  css  js  c++  java
  • 黄聪:C#反射 Reflection学习随笔(完结篇)_AX

    【正文】
    ①什么是反射?
    反射提供了封装程序集、模块和类型的对象。
    您可以使用反射动态地创建类型的实例(见④ ),将类型绑定到现有对象(这个不会),或从现有对象中获取类型(见②③ )。然后,可以调用类型的方法或访问其字段和属性。
    最最简单的反射:如下

     1using System;
     2using System.Reflection;
     3namespace TestReflection
     4{
     5    class Program
     6    {
     7        static void Main(string[] args)
     8        {
     9            //创建两个对象【object和Objetct好像没有区别啊??连提示都一样!】
    10            object A = new AX();
    11            Object B = new AXzhz();
    12            //获取对象的类型
    13            new TestObjectType().TestObjectTypeNow(A, B);            
    14        }

    15    }

    16
    17    class AX
    18    {
    19    }

    20
    21    class AXzhz
    22    {
    23    }

    24
    25    class TestObjectType
    26    {
    27        //构造函数的默认修饰为private
    28        internal void TestObjectTypeNow(object A, object B)
    29        {
    30            Type tpA = A.GetType();
    31            Type tpB = B.GetType();
    32            Console.WriteLine(tpA.FullName);
    33            Console.WriteLine(tpB.FullName);
    34            Console.ReadLine();
    35        }

    36    }

    37}


    输出结果:
    TestReflection.AX
    TestReflection.AXzhz
    【分析】通过对象实例(A,B),可以使用GetType()方法获取该对象属于哪个类.非类型转化后的类,而是构造该类型的类
    【应用】给个变量/对象实例,测试下它属于哪个类,顺带还给出该类所属的Assembly
    【附】另外一种获取类型的方法是通过Type.GetType以及Assembly.GetType方法,如:
           Type t = Type.GetType("TestReflection.AX");
        需要注意的是,前面我们讲到了命名空间和装配件的关系,要查找一个类,必须指定它所在的装配件
    Type类:表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。     发晕,对泛型没研究.

    ②我们获得的Type实例有什么用?
       ⅰ获得类名:如上面例子的FullName属性,返回TestReflection.AX
           这个也比较恶心,直接用A.ToString();返回的也是这个结果.
       ⅱ创建该类的对象.你首先通过ⅰ来获得类名AX
           AX ax = (AX)Activator.CreateInstance(tpA);
           都知道是AX类型了,怎么不new一个???鸡肋的东西.
          上面的【附】真不知道是干嘛吃的,都知道了类TestReflection.AX,直接new一个就可以了.
        ⅲ获得对象所属类的相关信息
             通过tpA的相关属性,来得到该类的相关信息.
             其实你通过A的相关属性,也可以得到该类的相关信息.还简单省事,真不知道Type类到底是干嘛吃的.

    窥一斑而知全豹,一个对象实例泄漏的密秘(这个比较爽)
    通过一个对象实例,我们可以获得包含这个对象实例的类的Assembly,进而获得整个Assembly的信息.

     1using System;
     2using System.Reflection;
     3namespace TestReflection
     4{
     5    class Program
     6    {
     7        public static void Main(string[] args)
     8        {
     9            object A = new AX();
    10            //获取对象所属的Assembly的所有类的基本信息
    11            new TestObjectType().TestObjectTypeNow(A);
    12        }

    13    }

    14
    15    class AX
    16    {
    17        internal int kkkkkkkk = 0;
    18        public int ooooooooo;
    19        private int property;
    20
    21        public int Property
    22        {
    23            get return property; }
    24            set { property = value; }
    25        }

    26        public void A()
    27        {
    28            Console.WriteLine("AX's function!~");
    29        }

    30    }

    31
    32    class AXzhz
    33    {
    34    }

    35
    36    class TestObjectType
    37    {
    38        //构造函数的默认修饰为private
    39        internal void TestObjectTypeNow(object A)
    40        {
    41            Type tpA = A.GetType();
    42            Assembly assembly = tpA.Assembly;
    43            Type[] types = assembly.GetTypes();
    44            foreach (Type type in types)
    45            {
    46                Console.WriteLine("【类名】"+type.FullName);
    47                //获取类型的结构信息
    48                ConstructorInfo[] myconstructors = type.GetConstructors();
    49                Show(myconstructors);
    50                //获取类型的字段信息
    51                FieldInfo[] myfields = type.GetFields();
    52                Show(myfields);
    53                //获取方法信息
    54                MethodInfo[] myMethodInfo = type.GetMethods();
    55                Show(myMethodInfo);
    56                //获取属性信息
    57                PropertyInfo[] myproperties = type.GetProperties();
    58                Show(myproperties);
    59                //获取事件信息,这个项目没有事件,所以注释掉了,
    60                //通过这种办法,还可以获得更多的type相关信息.
    61                //EventInfo[] Myevents = type.GetEvents();
    62                 //Show(Myevents);
    63            }

    64            Console.ReadLine();
    65        }

    66        //显示数组的基本信息
    67        public void Show(object[] os)
    68        {
    69            foreach (object var in os)
    70            {
    71                Console.WriteLine(var.ToString());
    72            }

    73            Console.WriteLine("----------------------------------");
    74        }

    75    }

    76}


    【注】通过测试,发现只能获得public类型的信息.

    ④动态创建对象实例【经典】
    是实现抽象工厂的基础,也是实现抽象工厂的核心技术,通过它,可以动态创建一个你想要的对象.如下面的例子是演示如何动态创建ChineseName或EnglishName的实例

     1using System;
     2using System.Reflection;
     3namespace TestReflection
     4{
     5    class AXzhz_sReflectionExample
     6    {
     7        public static void Main()
     8        {
     9            IName name=AbstractFactory.GetName();
    10            name.ShowName();
    11        }

    12    }

    13
    14    public class AbstractFactory
    15    {
    16        public static IName GetName()
    17        {
    18            //s的值以后从Web.config动态获取
    19            //把s赋值为:TestReflection.EnglishName,将显示英文名
    20            string s = "TestReflection.ChineseName";
    21            IName name = (IName)Assembly.Load("TestReflection").CreateInstance(s);
    22            return name;
    23        }

    24    }

    25    
    26    //声明一个接口,它有一个显示"名字"的功能
    27    public interface IName
    28    {
    29        void ShowName();
    30    }

    31
    32    //实现接口,显示中国名字
    33    public class ChineseName : IName
    34    {
    35        public void ShowName()
    36        {
    37            Console.WriteLine("我叫AX!");
    38            Console.ReadLine();
    39        }

    40    }

    41
    42    //实现接口,显示英国名字
    43    public class EnglishName:IName
    44    {
    45        void IName.ShowName()
    46        {
    47            Console.WriteLine("My name is AXzhz!");
    48            Console.ReadLine();
    49        }

    50    }

    51}


    ⑤获得整个解决方案的所有Assembly(这个有点用)
    如果你不太清楚自己的解决方案中都用到了哪些Assembly,可以使用下面的方法,如果再想得到Assembly里的信息,见③

     1using System;
     2using System.Reflection;
     3
     4namespace TestReflection
     5{
     6    class ShowAllAssembly
     7    {
     8        public static void Main()
     9        {
    10            //获得解决方案的所有Assembly
    11            Assembly[] AX = AppDomain.CurrentDomain.GetAssemblies();
    12            //遍历显示每个Assembly的名字
    13            foreach (object var in AX)
    14            {
    15                Console.WriteLine("Assembly的名字:"+var.ToString());                
    16            }

    17            //使用一个已知的Assembly名称,来创建一个Assembly
    18            //通过CodeBase属性显示最初指定的程序集的位置
    19            Console.WriteLine("最初指定的程序集TestReflection的位置:" + Assembly.Load("TestReflection").CodeBase);
    20            Console.ReadLine();
    21        }

    22    }

    23}

    24

  • 相关阅读:
    2017的结束2018的开始
    .NET Core使用swagger进行API接口文档管理
    数据库可扩展设计方案
    容量估算--随时更新
    分库分表设计基础
    利用bucardo搭建PostgreSQL数据库双活
    通过pgAgent实现PostgreSQL上的自动作业
    MySQL主主配置
    Oracle统计信息不准(谓词越界)造成的性能问题
    获取Oracle中SQL语句的执行计划
  • 原文地址:https://www.cnblogs.com/huangcong/p/1736244.html
Copyright © 2011-2022 走看看