zoukankan      html  css  js  c++  java
  • <转>反射 Type [DorpdowList绑定数据]

    1、先创建一个枚举enum

    此时,我们想到了使用枚举:

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

    2、通过typeof获取enum (使用泛型来达到代码重用)

    如果我们现在有另一个枚举,叫做TicketStatus,那么我们要将它绑定到列表,我们唯一需要改动的就是这里:

    Type enumType = typeof(BookingStatus); //将BookingStatus改作TicketStatus

    既然这样,我们何不定义一个泛型类来进行代码重用呢?我们管这个泛型类叫做EnumManager<TEnum>。

    public static class EnumManager<TEnum>
    {
        private static DataTable GetDataTable()
        {
           Type enumType = typeof(TEnum);  // 获取类型对象
           FieldInfo[] enumFields = enumType.GetFields();

           DataTable table = new DataTable();
           table.Columns.Add("Name", Type.GetType("System.String"));
           table.Columns.Add("Value", Type.GetType("System.Int32"));
           //遍历集合
           foreach (FieldInfo field in enumFields)
           {
               if (!field.IsSpecialName)
               {
                   DataRow row = table.NewRow();
                  row[0] = field.Name;
                  row[1] = Convert.ToInt32(field.GetRawConstantValue());
                  //row[1] = (int)Enum.Parse(enumType, field.Name); 也可以这样

                  table.Rows.Add(row);
               }
           }
           return table;
        }

        public static void SetListControl(ListControl list)
        {
           list.DataSource = GetDataTable();
           list.DataTextField = "Name";
           list.DataValueField = "Value";
           list.DataBind();
        }
    }

    OK,现在一切都变得简便的多,以后,我们再需要将枚举绑定到列表,只要这样就行了(ddl开头的是DropDownList,rbl开头的是RadioButtonList):

    EnumManager<BookingStauts>.SetListControl(ddlBookingStatus);
    EnumManager<TicketStatus>.SetListControl(rblTicketStatus);

     

    .Net 中反射的一个范例。

    不管是VS2005的智能提示,还是修改变量名时的重构功能,都使用了反射功能。在.Net FCL中,也经常能看到反射的影子,这里就向大家演示一个最常见的例子。大家知道,在CLR中一共有两种类型,一种是值类型,一种是引用类型。声明一个引用类型的变量并对类型实例化,会在应用程序堆(Application Heap)上分配内存,创建对象实例,然后将对象实例的内存地址返回给变量,变量保存的是内存地址,实际相当于一个指针;声明一个值类型的实例变量,则会将它分配在线程堆栈(Thread Stack)上,变量本身包含了值类型的所有字段。

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

    实际上,执行这样的一个比较并不需要我们自己编写代码,Microsoft已经为我们提供了实现的方法:所有的值类型继承自 System.ValueType, ValueType和所有的类型都继承自System.Object ,Object提供了一个Equals()方法,用来判断两个对象是否相等。但是ValueType覆盖了Object的Equals()方法。当我们比较两个值类型变量是否相等时,可以调用继承自ValueType类型的Equals()方法。

    public struct ValPoint {
        public int x;
        public int y;
    }
    static void Main(string[] args) {
        bool result;

        ValPoint A1;
        A1.x = A1.y = 3;

        ValPoint B1 = A1;            // 复制A的值给B
        result = A1.Equals(B1);
        Console.WriteLine(result);      // 输出 True;
    }

    你有没有想到当调用Equals()方法时会发生什么事呢?前面我们已经提到如果是值类型,会对两个变量的字段进行逐个的比较,看看每个字段的值是否都相等,但是如何获取变量的所有字段,遍历字段,并逐一比较呢?此时,你应该意识到又到了用到反射的时候了,让我们使用reflector来查看ValueType类的Equals()方法,看看微软是如何做的吧:

    public override bool Equals(object obj) {
        if (obj == null) {
           return false;
        }
        RuntimeType type = (RuntimeType)base.GetType();
        RuntimeType type2 = (RuntimeType)obj.GetType();
        if (type2 != 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]).InternalGetValue(a, false);
           object obj4 = ((RtFieldInfo)fields[i]).InternalGetValue(obj, false);
           if (obj3 == null) {
               if (obj4 != null) {
                  return false;
               }
           } else if (!obj3.Equals(obj4)) {
               return false;
           }
        }
        return true;
    }

    注意到上面加注释的那两段代码,可以看到当对值变量进行比较时,是会使用反射来实现。反射存在着性能不佳的问题(不仅如此,还存在着很多的装箱操作),由此可见,在值类型上调用Equals()方法开销是会很大的。但是这个例子仅仅为了说明反射的用途,我想已经达到了目的。上面的代码不能完全理解也不要紧,后面会再提到。

    7.小结

    看到这里,你应该对反射有了一个初步的概念(或者叫反射的一个用途):反射是一种宽泛的叫法,它通过 System.Reflection 命名空间 并 配合 System.Type 类,提供了在运行时(Runtime)对于 类型和对象(及其成员)的基本信息 以及 元数据(metadata)的访问能力。

     

    《转》http://www.cnblogs.com/JimmyZhang/archive/2008/01/27/Reflection-Part1.html

  • 相关阅读:
    MKMapVIew学习系列2 在地图上绘制出你运行的轨迹
    WPF SDK研究 Intro(6) WordGame1
    WPF SDK研究 Intro(3) QuickStart3
    WPF SDK研究 Layout(1) Grid
    WPF SDK研究 目录 前言
    WPF SDK研究 Intro(7) WordGame2
    WPF SDK研究 Layout(2) GridComplex
    对vs2005创建的WPF模板分析
    WPF SDK研究 Intro(4) QuickStart4
    《Programming WPF》翻译 第6章 资源
  • 原文地址:https://www.cnblogs.com/p_db/p/2405367.html
Copyright © 2011-2022 走看看