反射初步

反射初步

 

首先来认识一下反射,咱们每次咱认识一个新东西的时候,需要了解这么一个情况,这个东西是啥,它的作用是啥,我学他有啥用,搞明白了这三件事就算可以了.

 

说实话,楼主学了.NET也得一年多了吧,一次反射也没用到过,当然楼主涉世未深,也不了解反射,最近几天楼主和大家一起研究研究反射的东西.

 

反射初步

 

假设你在开发一个据点预订系统,在订单处理过程中需要标示酒店预订的状态:未提交,已提交,已取消,受理中,已退回,已订妥,已过期.此时,很多开发人员可能会这样建表:

 

                   BookingStatus

Id

Status

1

未提交

2

已提交

3

已取消

4

受理中

5

已退回

6

已订妥

7

已过期

 

这个表的作用只是用来查询,不会提供给用户增删改的操作.在程序中获取这个表的数据时,经常是这种情况:需要根据预定状态对订单进行筛选,此时通常的做法是使用一个下拉菜单(DropDownList),通过ADO.NET获取这个表的数据,然后再将DropDownListTest设为Status字段,Value设为Id字段.

 

采用这种做法时,会有下面这2个问题:

(1).如果还存在比如航班预定之类的状态,那么需要在数据库中创建很多类似的小表,从而导致数据库表的数目态度.

(2).使用DropDownList等控件获取表内容时,经常需要连接到数据库进行查询,这可能会影响性能.

 

同时注意到以下三点:

(1).这个表不会改动

(2).这表一般不会在数据库联合产讯中使用到.

(3).在应用程序中,这表经常作为DropDownList或者其他控件的数据源.

 

 

因为状态在定义好以后就不改变了,那么使用数据库先得多余了,咱们可以使用数组来表示预定状态,这样可以从数据库中删除这个表了.这个数组的内容可能会是这样:

string[] BookingStatus = { "NoUse","未提交","已取消","已退回","已订妥","已过期"};


数组是从下标0开始的,所以咱们把下标0的元素设置成别的东西.

 

使用数组就能把上面的两个问题都给解决了.既不用建表,也不用连接到数据库.

 

这样的话使用一个订单类HotelOrder,其属性StatusId代表订单状态,这样的话确实有一点不太方便,当需要更新订单状态的状态值时,除非记住所有状态的数字值,否则就要去查看BookingStatus数组的定义,然后根据状态值在数组中的位置来为对象的属性赋值.

 

假设系统的操作人员分为两组,一组为消费者,负责下订单;一组为操作员,负责处理订单.对于消费者来说,只要看到未提交,已提交,已取消,已订妥四个状态,对应的值分别是1,2,3,6.对于操作员来说,需要看到全部的订单状态.

 

如果继续使用数组来定义状态,就会发下你个问题:默认将订单状态值与数组的索引一一对应了起来.当这种一一对应的关系被打破时,使用数组的方法就失效了,因为如果不利用数组索引,就没有额外的地方去存储状态的数字值,这个时候可使用枚举:

    public enum BookingStatus
    {
        未提交=1,
        已提交,
        已取消,
        已订妥=6
    }


使用枚举的原因是我们可以让VS的智能提示完全可以起到作用.将枚举绑定到DropDownList下拉列表中,可以绑定到下拉列表的有两种状态:一种是实现了IEnumerable接口普的可枚举类型,比如ArrayList,String[],List<T>;一类是实现了IListSource的数据源,比如DataTable,DataSet.可是,枚举enum是一个基本类型,他不会实现任何接口,显然无法将枚举绑定到DropDownList.

 

 

不管是VS的智能提示,还是修改变量名时的重构功能,都使用了反射的功能.下面向大家展示一个基本的案例,C#中一共有两种类型,一种是值类型,一种是引用类型.声明一个引用类型的变量并实例化类型,会在应用程序堆(Application Heap)上分配空间,创建对象实例,然后将对象实例的内存地址返回给变量,变量保存的是内存地址,实际相当于一个指针;声明一个值类型的实例变量,则会将它分配在线程堆栈(Thread Stack),变量本身包含了值类型的所有字段.

 

现在假设需要比较两个对象是否相等.当比较两个引用类型的变量是否相等时,比较的是这两个变量所指向的是不是堆上的同一个实例,即内存地址是否相同.而比较值类型变量时是否相等时,咋办?因为变量本身就包含了值类型所有的字段(数据),所以在比较时,就需要对两个变量的字段进行逐个的一对一的比较,看看每个字段的值是否相等,如果任何一个字段不相等,就返回false.

 

进行这样的比较不需要我们自己编写代码,因为所有的值类型都继承自System.ValueType,ValueType继承自System.Object,Object提供了一个方法,用来判断两个对象是否相等.但是ValueType类型覆盖了ObjectEquals()方法.当比较两个值类型变量时,会调用继承自ValueType类型的Equals()方法.

 

那么ValueType中的Equals()方法如何获取值类型的所有字段,并进行一一对比呢?显然,咱们打开Reflector来查看ValueType类的Equals()方法,看看具体是如何实现的:


 

[SecuritySafeCritical, __DynamicallyInvokable]
public override bool Equals(object obj)
{
    if (obj == null)
    {
        return false;
    }
    RuntimeType type = (RuntimeType) base.GetType();
    if (((RuntimeType) obj.GetType()) != type)
    {
        return false;
    }
    object a = this;
    if (CanCompareBits(this))
    {
        return FastEqualsCheck(a, obj);
    }
    FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    for (int i = 0; i < fields.Length; i++)
    {
        object obj3 = ((RtFieldInfo) fields[i]).UnsafeGetValue(a);
        object obj4 = ((RtFieldInfo) fields[i]).UnsafeGetValue(obj);
        if (obj3 == null)
        {
            if (obj4 != null)
            {
                return false;
            }
        }
        else if (!obj3.Equals(obj4))
        {
            return false;
        }
    }
    return true;
}

 

反射最大的问题就是性能不佳,由此可见,在值类型上调用Equals()方法开销会很大.但是这个例子仅仅是为了说明发射的应用场景.

 

反射其实是一种宽泛的叫法,它通过System.Reflection命名空间并配合System.Type,提供了在运行时(Runtime)对类型和类型成员的元数据的访问能力.

reflector下载地址:

http://www.waitalone.cn/reflector-v8-crack-version.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值