【学习笔记】C# System.Type类(反射)

  • Post author:
  • Post category:其他




反射


反射用到的主要类:

System.Type 类–通过这个类可以访问任何给定数据类型的信息。

System.Reflection.Assembly类–它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。

System.Type类:System.Type 类对于反射起着核心的作用。但它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。


新建一个NewClass类来测试反射

class NewClass
    {
        public string a;
        public int b;
        public string Name { get; set; }
        public int Age { get; set; }
        public NewClass(string m, int n) 
        {
            a = m;
            b = n;
        }

        public NewClass() 
        {
            Console.WriteLine("调用构造函数");
        }
        public void Show() 
        {
            Console.WriteLine($"生成一个对象a{a}b{b}名字{this.Name}年龄{this.Age}");
        }
    }

测试代码:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("一、查看类中的构造方法:");
            #region 查看类中的构造方法
            NewClass nc1 = new NewClass();
            Type t1 = nc1.GetType();
            ConstructorInfo[] ci1 = t1.GetConstructors();
            foreach (var item in ci1)
            {
                Console.WriteLine("count");
                ParameterInfo[] pi = item.GetParameters();
                foreach (ParameterInfo p in pi)
                {
                    Console.Write(p.ParameterType.ToString() + " " + p.Name + ",");
                }
                Console.WriteLine("");
            }
            Console.WriteLine("----------------------------------------------------");
            #endregion

            #region 用构造函数动态生成对象
            Console.WriteLine("二、用构造函数动态生成对象:");
            Type t2 = typeof(NewClass);
            //参数数组
            Type[] pt2 = new Type[2];
            pt2[0] = typeof(string);
            pt2[1] = typeof(int);
            //根据参数类型获取构造函数,有可能有多个构造函数
            ConstructorInfo ci2 = t2.GetConstructor(pt2);
            object[] obj2 = new object[2] { "s", 1 };
            //调用构造函数,传递参数为obj
            object o2 = ci2.Invoke(obj2);
            //测试调用结果是否成功
            ((NewClass)o2).Show();
            Console.WriteLine("----------------------------------------------------");
            #endregion

            #region 用Activator生成对象
            Console.WriteLine("三、用Activator生成对象:");
            Type t3 = typeof(NewClass);
            //构造函数的参数
            object[] obj3 = new object[2] { "hello", 11 };
            //用Activator的CreateInstance静态方法,生成新对象
            object o13 = Activator.CreateInstance(t3, "sun", 44);
            object o23 = Activator.CreateInstance(t3, obj3);
            object o33 = Activator.CreateInstance(t3);
            ///Activator.CreateInstance第一个参数为需要创建对象的类型,后面的为调用构造函数的参数,上面的三种格式都可以,只是调用的构造函数不同而已
            ((NewClass)o13).Show();
            Console.WriteLine("----------------------------------------------------");
            #endregion

            #region 查看类中的属性
            Console.WriteLine("四、查看类中的属性:");
            NewClass nc4 = new NewClass();
            Type t4 = nc4.GetType();
            PropertyInfo[] pis4 = t4.GetProperties();
            foreach (var pi in pis4)
            {
                Console.WriteLine(pi.Name);
            }
            Console.WriteLine("----------------------------------------------------");

            #endregion

            #region 查看类中的public方法
            Console.WriteLine("五、查看类中的public方法:");
            NewClass nc5 = new NewClass();
            Type t5 = nc5.GetType();
            MethodInfo[] mis5 = t5.GetMethods();
            foreach (var mi in mis5)
            {
                Console.WriteLine(mi.ReturnType + " " + mi.Name);
            }
            Console.WriteLine("----------------------------------------------------");

            #endregion

            #region 查看类中的public字段
            Console.WriteLine("六、查看类中的public字段:");
            NewClass nc6 = new NewClass();
            Type t6 = nc6.GetType();
            FieldInfo[] fis6 = t6.GetFields();
            foreach (var fi in fis6)
            {
                Console.WriteLine(fi.Name);
            }
            Console.WriteLine("----------------------------------------------------");
            #endregion

            #region 用反射生成对象,并调用属性、方法、字段进行操作
            Console.WriteLine("七、用反射生成对象,并调用属性、方法、字段进行操作");
            NewClass nc7 = new NewClass();
            Type t7 = nc7.GetType();
            object obj7 = Activator.CreateInstance(t7);
            //取得ID字段
            FieldInfo fi7 = t7.GetField("a");
            //给ID字段赋值
            fi7.SetValue(obj7, "sun");
            //取得Name属性
            PropertyInfo pi71 = t7.GetProperty("Name");
            //给Name属性赋值
            pi71.SetValue(obj7, "sun", null);
            //取得Age属性
            PropertyInfo pi72 = t7.GetProperty("Age");
            //给Age属性赋值
            pi72.SetValue(obj7, 200, null);
            //取得show方法
            MethodInfo mi7 = t7.GetMethod("Show");
            //调用show方法
            mi7.Invoke(obj7, null);
            Console.WriteLine("----------------------------------------------------");
            #endregion

            Console.ReadKey();
        }
    }



System.Reflection.Assembly


Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。

通过程序集名称返回Assembly对象


Assembly ass = Assembly.Load("ClassLibrary831");

通过DLL文件名称返回Assembly对象


Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");


通过Assembly获取程序集中类


Type t = ass.GetType("ClassLibrary831.NewClass");


//参数必须是类的全名

通过Assembly获取程序集中所有的类


Type[] t = ass.GetTypes();

如果要反射一个DLL中的类,并且是未知的类型,则可以这样操作:


Assembly assembly=Assembly.LoadFile("程序集路径,不能是相对路径");//加载程序集(exe或dll)



Object obj=assembly.CreateInstance("类的完全限定名(包括命名空间)");//创建类的实例



版权声明:本文为qq_38310237原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。