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

  • 相关阅读:
    signal(SIGCHLD, SIG_IGN)和signal(SIGPIPE, SIG_IGN);
    关于pthread_cond_wait使用while循环判断的理解
    linux的sleep()和usleep()的使用和区别
    C中结构体的存储分配
    扯扯python的多线程的同步锁 Lock RLock Semaphore Event Condition
    线程属性的初始化以及销毁
    Mysql数据库一个表字段中存了id,并以逗号分隔,id对应的详细信息在另一个表中
    sqlyog 注册码
    Oracle 12C卸载图文教程
    Oracle12c Release1安装图解(详解)
  • 原文地址:https://www.cnblogs.com/p_db/p/2405367.html
Copyright © 2011-2022 走看看