漫谈反射机制(一)

原创 2012年03月22日 16:40:34

 

开篇:总算有点空闲时间来写点自己的东西了,今天我要探讨的是关于.NET的反射机制,反射是一个比较神奇的技术,如果在实际项目中能很好的运用反射技术,那会省去很多麻烦。有朋友会问,何为反射?其实可以从字面上来进行理解,我们做实际项目的时候,编译的时候会自动把一些项目等编译成为dll或者exe吗?如下图:

 

反射说的通俗点就是把一些已经生成的反过来映射出来,从而我们可以用这些信息;这下应该理解力吧(还没理解的话,那就继续下面);

一、基本概念

反射:反射是一个运行库类型发现的过程。 通过反射可以得到一个给定程序集所包含的所有类型的列表,这个列表包括给定类型中定义的方法、字段、属性和事件。也可以动态的发现一组给定类支持的接口、方法的参数和其他相关信息如基类、命名空间、数据清单等。

二、命名空间         

     1.System.Reflection命名空间内的各类型(记得要引用这个命名空间)

             (1)Assembly    通过它可以加载、了解和操纵一个程序集

              (2) AssemblyName 通过它可以找到大量隐藏在程序集的身份中的信息,如版本信息、区域信息等

              (3) EventInfo  事件的信息

              (4) FieldInfo  字段的信息

              (5) MethodInfo  方法的信息

              (6) ParameterInfo  参数的信息

              (7)PropertyInfo  属性的信息

              (8) MemberInfo  是抽象基类,为  EventInfo、FieldInfo 、MethodInfo、PropertyInfo等类型定义了公共的行为。    

              (9) Module 用来访问带有多文件程序集的给定模块  

      2.System.Type类 

         System.Type支持的成员可以分为这样几类

               (1) Is***   用来检查一个类型的元数据,如IsAbstract、IsClass、IsValueType等等

               (2) Get***  用来从类型得到指定项目,如GetEvent()得到类型的一个指定的事件(EventInfo)。 另外,这些方法都有一个单数版本和一个复数版本。如GetEvent()对应有一个复数版本GetEvents(), 该方法返回一个相关的EventInfo数组 

               (3) FindMembers()   根据查询条件返回一个MemberInfo类型的数组

               (4)GetType()  该静态方法根据一个字符串名称返回一个Type实例

               (5)InvokeMember()  对给定项目进行晚期绑定

      3.得到一个Type类型实例的三种方法(因为Type是一个抽象类,所以不能直接使用new关键字创建一个Type对象)

                (1) 使用System.Object.GetType()

                                    e.g:    People=new People();  //---------定义pe为People类的一个对象 

                                              Type t=pe.GetType(); 

                 (2)使用System.Type.GetType()静态方法,参数为类型的完全限定名

                                    e.g:     Type t=Type.GetType("Entity.People");该方法被重载,允许指定两个布尔类型的参数,一个用来控制当前类型不能找到时是否抛出异常,另一个用来指示是否区分字符串大小写                         

    Type t=Type.GetType("Entity.People",false,true);

    注意到传入的字符串并没有包含类型所在的程序集信息,此时该类型便被认为是定义在当前执行的程序集中的。要得到一个外部私有程序集的类型元数据时,字符串参数必须使用类型完全限定名加上类型所在程序集的友好名字

                         e.g:  Type t=Type.GetType("Entity.People","Entity");//------"Entity"即为类型所在程序集的友好名字 

                             嵌套类型:传入的字符串可以指定一个+标记来表示一个嵌套类型,如希望得到一个嵌套在People类中的枚举类型City的类型信息,

                           则可以这样  e.g:   Type t=Type.GetType("Entity.People+City");

                       (3) 使用typeof运算符         e.g:   Type  t=typeof(People);

三种方法的比较:

1、使用object.GetType():使用该方法,则首先必须建立一个实例,这样不利于进行动态的使用;

2、使用typeof(object):使用该方法,也是必须先建立一个实例;

3、使用Type.GetType(类型的完全限定名):使用该方法是首选,因为可以其扩张性好(这里也许有人会弱弱的问,何以见得扩展性好?因为参数是字符串,所以可以根据需要来进行赋值);

 

说了这么多,可能还是在苦苦寻思~~,到底这个有何用处?别纸上谈兵了,还是来点实际的有说服力;

下面是一个实例,简单的运用了前面介绍的知识,实现了对一个Type对象的反射,包括反射其所有可见字段、方法、属性、事件。反射类型的基本属性。并将其中一个方法的详细信息列了出来

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;//必须要引用该命名空间,才能使用相关方法
using System.Collections;//为了后面能使用IEnumerable所实现的方法

namespace ConsoleApplication1
{
    public class PeopleClass : Interface1, IEnumerable
    {
        public string pbname = string.Empty;
        private string username = string.Empty;
        private int age = 0;
        Array name = null;


        public string UserName
        {
            get { return username; }
            set { username = value; }
        }

        public int Age
        {

            get { return age; }
            set { age = value; }
        }

        public string getStr()
        {
            return "hello";
        }

        private string getName()
        {
            return "abc";
        }

        public delegate void PeopleNameHandler(string x);
        public event PeopleNameHandler OnChangeName; //------定义了一个改变姓名的事件
        private event PeopleNameHandler OnOtherChangeName;

        public void ChangeName(string name)//---改名的方法
        {
            UserName = name;
        }

        public IEnumerator GetEnumerator()//---实现接口
        {
            return name.GetEnumerator();
        }
    }

}


 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Reflection;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Type tp = Type.GetType("ConsoleApplication1.PeopleClass");
            GetMethods(tp);
            GetEvents(tp);
            GetFields(tp);
            GetInterFaces(tp);
            GetProperties(tp);
            GetMethodInfo(tp, "ChangeName");
            Console.ReadLine();
        }

        /// <summary>
        /// 显示这个类型的所有方法名
        /// </summary>
        /// <param name="tp">类型对象</param>
        public static void GetMethods(Type tp)
        {
            if (tp != null)
            {
                Console.WriteLine("该类型的所有方法:\n");
                try
                {
                    MethodInfo[] mi = tp.GetMethods();
                    foreach (MethodInfo item in mi)
                    {
                        Console.WriteLine("\t方法名:{0}", item.Name);
                    }
                }
                catch (Exception)
                {

                    throw;
                }
            }
        }

        /// <summary>
        /// 显示这个类型的的某个方法的详细信息
        /// </summary>
        /// <param name="tp">类型对象</param>
        public static void GetMethodInfo(Type tp, string methodName)
        {
            if (tp != null)
            {
                Console.WriteLine("该类型方法的详细信息:\n");
                try
                {
                    MethodInfo mi = tp.GetMethod(methodName);
                    Console.WriteLine("\t方法返回类型:{0}", mi.ReturnType);
                }
                catch (Exception)
                {

                    throw;
                }
            }
        }

        /// <summary>
        ///显示该类型的所有属性 
        /// </summary>
        /// <param name="tp"></param>
        public static void GetProperties(Type tp)
        {
            if (tp != null)
            {
                Console.WriteLine("该类型的所有属性:\n");
                try
                {
                    PropertyInfo[] pi = tp.GetProperties();
                    foreach (PropertyInfo item in pi)
                    {
                        Console.WriteLine("\t属性名:{0}", item.Name);
                    }
                }
                catch (Exception)
                {

                    throw;
                }
            }
        }

        /// <summary>
        ///显示该类型的所有事件
        /// </summary>
        /// <param name="tp"></param>
        public static void GetEvents(Type tp)
        {
            if (tp != null)
            {
                Console.WriteLine("该类型的所有事件:\n");
                try
                {
                    EventInfo[] ei = tp.GetEvents();
                    foreach (EventInfo item in ei)
                    {
                        Console.WriteLine("\t字段名:{0}", item.Name);
                    }
                }
                catch (Exception)
                {

                    throw;
                }
            }
        }

        /// <summary>
        ///显示该类型的所有字段 
        /// </summary>
        /// <param name="tp"></param>
        public static void GetFields(Type tp)
        {
            if (tp != null)
            {
                Console.WriteLine("该类型的所有字段:\n");
                try
                {
                    FieldInfo[] fi = tp.GetFields();
                    foreach (FieldInfo item in fi)
                    {
                        Console.WriteLine("\t字段名:{0}", item.Name);
                        Console.WriteLine("\t字段类型:{0}", item.FieldType);
                    }
                }
                catch (Exception)
                {

                    throw;
                }
            }
        }

        public static void GetInterFaces(Type tp)
        {
            Console.WriteLine("该类型的所实现的接口:\n");
            Type[] it = tp.GetInterfaces();  //-----------对GetInterfaces()的调用返回一个 Type类型 的数组(说明其实接口也是一种类型)
            foreach (Type p in it)
            {
                Console.WriteLine("\t接口名:{0}", p.Name);
            }
        }
    }
}


 

【实现效果】



【总结】

结合这些神乎其神的源代码和运行效果,总结如下

            1.属性在编译后成为了get_属性名()和set_属性名()两个独立的方法

            2.OnChangeName事件的注册(+=)和取消注册(-=)分别成为了add_ OnChangeName ()和remove_ OnChangeName方法

            3.私有(private)的成员(字段,方法,事件,属性)都没有显示出来;

            4.基类的基类System.Object的成员GetType()和Equals()也被打印了出来,基类的共有方法也被打印出来

这个私生的(private)就是不同,世道就是这样呵呵,私有的都不能显身了。今天的反射就暂时讲到这里吧,下次欢迎一起探讨;

 

声明:本文章欢迎阅览,当然这其中也许有一些问题,文明交流,文明评论,共同分享,共同快乐,谢谢!

(未完待续)

C# 技术漫谈 反射机制

反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等。公共语言运行...

java的反射机制使用漫谈

1.机制介绍         Java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方...

java反射机制

  • 2016年06月05日 21:04
  • 7KB
  • 下载

Java反射机制

  • 2015年02月27日 21:08
  • 845KB
  • 下载

iOS反射机制: objc_property_t的使用

objc_property_t在实际开发中用得还是比较多的,例如需要获取一个注册类的属性,或者判断属性的类型,再或者获取属性之后自动给其赋值等等 这里举个获取注册类的所有属性的例子,代码如下: ...

Java 语言的反射机制

  • 2013年08月29日 22:43
  • 185KB
  • 下载

Java基础与提高干货系列——Java反射机制

前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来。那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现。 正文 Java反射机制定义 Java...

Java泛型和反射机制

  • 2014年01月07日 11:20
  • 626KB
  • 下载

Java中类的反射机制

  • 2013年12月18日 19:58
  • 245KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:漫谈反射机制(一)
举报原因:
原因补充:

(最多只允许输入30个字)