• 20181114_反射_泛型反射


    反射的核心: 动态; 利用反射, 一切都可以动态实现

    一. 以下代码用到的People和PeopleDTO类代码:

    /// <summary>
        /// 基于数据库查询得到这样一个类; 和数据库对应
        /// </summary>
        public class People
        {
            public People()
            {
                Console.WriteLine("{0}被创建", this.GetType().FullName);
            }
    
            public int Id { get; set; }
            public string Name { get; set; }
            public string Description;
    }
    
    /// <summary>
        /// 对应着界面绑定; 和程序对应
        /// </summary>
        public class PeopleDTO
        {
            public PeopleDTO()
            {
                Console.WriteLine("{0}被创建", this.GetType().FullName);
            }
            public int Id { get; set; }
            public string Name { get; set; }//ShortName  特性
    
            public string Description;
        }

    二. 对已知类型的简单反射

    People people = new People();
                        people.Id = 123;
                        people.Name = "wukong";
                        people.Description = "大师兄";
    
                        {
                            //对已知类型的简单反射  注意: 反射的写法有很多种,前面使用程序集的字符, 这里直接使用People, 都是为了获取类型, 反射最主要的问题就是拿到类型, 而不用管通过什么方法拿到
                            Type type = typeof(People);
                            object oPeople = Activator.CreateInstance(type); //创建一个默认对象
                            foreach (var item in type.GetProperties()) //type.GetProperties()表示 获取属性信息
                            {                                           // type.GetFields() 表示获取字段信息
                                                                        //在C#中规定, 有get; set; 的是属性; 没有get;set;的是字段
                                                                    
                                Console.WriteLine(type.Name);
                                Console.WriteLine(item.Name); //每一个属性的名称
                                Console.WriteLine(item.GetValue(oPeople ));//获取属性的值
                                if (item.Name.Equals("Id"))
                                {
                                    item.SetValue(oPeople, 223);
                                }
                                else if (item.Name.Equals("Name"))
                                {
                                    item.SetValue(oPeople, "八戒");
                                }
                            }

    三.  基于泛型的反射

    a)       泛型类代码:

    public class GenericClass<T, W, X>
        {
            public void Show(T t, W w, X x)
            {
                Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name);
            }
    }
    

     b)  使用反射创建一个泛型类的实例代码:

    //对于泛型的反射; 其中GenericClass `3 ; 因为泛型编译之后就会生成一个这样的类; `表示占位符; 3表示GenericClass有3个类型的参数; 如果有两个, 那么这里就是个2
    Assembly assembly = Assembly.Load("MyDB.SqlServer");
    Type type = assembly.GetType("MyDB.SqlServer.GenericClass`3");
    //这种方式无法创建改对象的实例的; 因为没有为泛型指定实例化对象
    //object oGeneric = Activator.CreateInstance(type);
    
    //为泛型指定类型进行实例化
    Type newType = type.MakeGenericType(new Type[] { typeof(int), typeof(string), typeof(DateTime) });
    //使用newType创建泛型的类型
    object oGeneric = Activator.CreateInstance(newType);

    四. 使用反射调用泛型类的泛型方法

    a)   GenericDouble类代码:

    public class GenericDouble<T>
        {
            public void Show<W, X>(T t, W w, X x)
            {
                Console.WriteLine("t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name, x.GetType().Name);
            }
        }
    

     b) 反射调用泛型类的泛型方法

    Type typeGenericDouble = assembly1.GetType("MyDB.SqlServer.GenericDouble`1");
    // 将类的泛型规定为int类型; 因为它是泛型的, 使用(实例化)之前必须要指定泛型的类型
    //使用反射时, 则需要使用typeof(int)将泛型的T指定为想要创建的类型. 这里指定为int类型
    Type newType = typeGenericDouble.MakeGenericType(new Type[] { typeof(int) });
    //创建对象,
    object oGeneric = Activator.CreateInstance(newType);
    //找对象里面的方法
    MethodInfo method = newType.GetMethod("Show");
    //method.IsGenericMethod  //判断此方法是不是一个泛型方法
    //MakeGenericMethod 指定方法的类型
    MethodInfo methodNew = method.MakeGenericMethod(new Type[] { typeof(string), typeof(DateTime) });
    //传递的参数类型, 必须和上面的参数类型保持一致
    methodNew.Invoke(oGeneric, new object[] { 123, "沙和尚", DateTime.Now });  

     五. 基于反射, 利用泛型实现DTO

    a)   将People转成PeopleDTO; 普通硬编码, 死编码

    People people = new People();
    people.Id = 123;
    people.Name = "wukong";
    people.Description = "大师兄";
    
    PeopleDTO peopleDTO = new PeopleDTO()
    {
        Id = people.Id,
        Name = people.Name,
        Description = people.Description
    };//硬编码转换  效率最高
    

     b) 利用反射实现

    Type typePeople = typeof(People);
    
    Type typePeopleDTO = typeof(PeopleDTO);
    object peopleDTO = Activator.CreateInstance(typePeopleDTO);
    foreach (var prop in typePeopleDTO.GetProperties()) //访问所有属性
    {
            #region 使用属性名称字符串来判断; 低级方法
            //if (prop.Name.Equals("Id"))
            //{
            //    //object value = typePeople.GetProperty("Id").GetValue(people);
            //    object value1 = typePeople.GetProperty(prop.Name).GetValue(people);
            //    prop.SetValue(peopleDTO, value1);
            //}
            //else if (prop.Name.Equals("Name"))
            //{
            //    //object value = typePeople.GetProperty("Name").GetValue(people);
            //    object value1 = typePeople.GetProperty(prop.Name).GetValue(people);
            //    prop.SetValue(peopleDTO, value1);
            //}
            #endregion
            //如果两个类的字段名称都一样, 则可以使用下面的方法; 如果两个类的字段不一样, 则需要使用特性
            object value = typePeople.GetProperty(prop.Name).GetValue(people);
            prop.SetValue(peopleDTO, value);
     }
    //访问字段
    foreach (var filed in typePeopleDTO.GetFields())
    {
        object value = typePeople.GetField(filed.Name).GetValue(people);
        filed.SetValue(peopleDTO, value);
    }
    

      

  • 相关阅读:
    仰视源代码,实现strcmp
    Wicket实战(一)概述
    在弱网传输的情况下,是怎么做到节约流量的(面试小问题,Android篇)
    nRF52832之硬件I2C
    Android开源项目SlidingMenu的学习笔记(一)
    MVC设计模式
    报表应用结构优化之数据分库存储
    extern &quot;C&quot; 的含义:实现C++与C及其他语言的混合编程
    phpstorm改变文件编码由utf变为gbk
    mysql database 格式的查看和改变
  • 原文地址:https://www.cnblogs.com/wxylog/p/9960543.html
Copyright © 2020-2023  润新知