漫谈反射机制(一)

 

开篇:总算有点空闲时间来写点自己的东西了,今天我要探讨的是关于.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)就是不同,世道就是这样呵呵,私有的都不能显身了。今天的反射就暂时讲到这里吧,下次欢迎一起探讨;

 

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

(未完待续)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java安全漫谈是一本关于Java安全的书籍,深入探讨了Java应用程序在网络环境中的安全性和相关的安全漏洞。该书内容涵盖了Java安全基础、Java虚拟机的安全机制、Java安全管理、Java安全开发等方面的知识。 首先,Java安全基础部分介绍了Java安全模型的原理和特点,包括Java类库的安全特性、权限管理和访问控制、安全策略配置等。这部分内容可帮助开发人员了解Java应用程序的安全需求,并提供相应的解决方案。 其次,Java虚拟机的安全机制是Java应用程序的基石。该书介绍了Java虚拟机的安全沙箱和类加载机制,并讨论了如何利用这些安全机制避免恶意代码的执行和隐患的防范。 此外,Java安全管理部分从用户角度出发,介绍了Java应用程序的安全管理工具和技术,如Java安全策略文件、权限管理和安全认证等。开发人员可以通过合理配置和使用这些工具来提高Java应用程序的安全性。 最后,该书还涉及了Java安全开发过程中的一些最佳实践和常见安全漏洞,如输入验证、跨站脚本攻击(XSS)、SQL注入、跨站请求伪造(CSRF)等。通过学习和掌握这些知识,开发人员可以编写出更加安全的Java应用程序。 总而言之,Java安全漫谈是一本全面讨论Java安全的书籍,内容涵盖了Java安全基础、Java虚拟机的安全机制、Java安全管理和Java安全开发等方面的知识。它对于开发人员和安全从业人员来说,都是一本重要的参考书,有助于提高Java应用程序的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值