C# 反射学习

本文详细介绍了.NET中的反射技术,包括如何使用反射动态创建对象、调用方法等。同时,文章还深入探讨了Type对象、元数据的概念及其应用。

反射

反射可以做什么?

动态创建对象

动态赋值

动态调用方法

反射简介

.Net中的类被编译成IL( Intermediate Language 微软中间语言),反射就可以在运行时获取类的信息(字段,方法,构造函数,父类),还可以动态创建对象调用成员

每个对应一个Type对象(Type是用来描述类,并非描述对象)

每个方法对应一个MethodInfo对象

每个属性对应一个PropertyInfo

这些就是类、方法、属性的**“元数据”**(meta data)。

元数据Metadata),又称中介数据中继数据,为描述数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置、历史数据、资源查找、文件记录等功能。

元数据是一种二进制信息,以非特定语言的方式描述在代码中定义的每一类型和成员。

获取Type对象的三个方法

using ConsoleApp1;
//从对象获取
Student student = new Student();
Type type = student.GetType();
Console.WriteLine(type);//ConsoleApp1.Student
//从类名获取
Type type1 = typeof(Student);
Console.WriteLine(type1);//ConsoleApp1.Student
//从全类名获取
var type2 = Type.GetType("ConsoleApp1.Student");
Console.WriteLine(type2);//ConsoleApp1.Student

因为一个类对应一个Type对象,所以上述方法获取的type、type1、type2都为同一个对象

通过Object.ReferenceEquals(Object, Object) 方法来验证

Console.WriteLine(Object.ReferenceEquals(type,type1));//True
Console.WriteLine(Object.ReferenceEquals(type, type2));//True

通过反射动态创建对象

Activator.CreateInstance 方法

    public class Person
    {
        public void Say()
        {
            Console.WriteLine("我是Person");
        }
    }
Person person = new Person();
Type t1 = person.GetType();//通过person实例来获取person类的对应的type对象
//Activator.CreateInstance 方法 使用最符合指定参数的构造函数创建指定类型的实例。
object obj = Activator.CreateInstance(t1);//动态创建t1指向的类的对象,相当于new person
(obj as Person).Say();//我是Person

Type的常见成员

Type类是一个抽象类
我们通过Type t1 = typeof(Person);获取到的t1是 Type类的子类的子类 的对象

            Type t1 = typeof(Person);
            Console.WriteLine(t1);//ConsoleApp2.Person
            Console.WriteLine(t1.GetType());//System.RuntimeType
            //Type.BaseType属性 获取父类Type
            Console.WriteLine(t1.GetType().BaseType);//System.Reflection.TypeInfo
            Console.WriteLine(t1.GetType().BaseType.BaseType);//System.Type

Type.FullName 属性和MemberInfo.Name 属性

MemberInfo.Name 属性

获取当前Type对象的对应类名

Type.FullName 属性

获取当前Type对象的对应完整类名(命名空间.类名)

            Type t1 = typeof(Person);
            Console.WriteLine(t1.Name);//Person
            Console.WriteLine(t1.FullName);//ConsoleApp2.Person

Type.GetConstructorType.GetConstructors 方法 获取构造函数

根据参数类型找到对应的构造函数
    public class Person
    {
        public Person()
        {
        }
        public Person(string name)
        {
        }
		public int id;
        private int iid;
        public string Name { get; set; }
        public int Age { get; set; }
        public void SayHi()
        {
            Console.WriteLine($"大家好,我是{this.Name},我的年龄是{this.Age}");
        }
    }
            ConstructorInfo c1 = t1.GetConstructor(new Type[0]);//获取无参构造函数
            ConstructorInfo c2 = t1.GetConstructor(new Type[] { typeof(string) });//
            Console.WriteLine(c1);//Void .ctor()
            Console.WriteLine(c2);//Void .ctor(System.String)
            ConstructorInfo c3 = t1.GetConstructor(new Type[] { typeof(int), typeof(int) });
            Console.WriteLine(c3);//未找到,打印出空
获取所有有构造函数
            ConstructorInfo[] constructors = t1.GetConstructors();//获取所有的构造函数
            foreach (var item in constructors)
            {
                Console.WriteLine(item);
                //Void .ctor()
                //Void .ctor(System.String)
            }

Type.GetFields 方法 获取字段

获取公有字段
            FieldInfo[] fields = t1.GetFields();//GetFields() 返回当前 Type 的所有公共字段。
            foreach (var item in fields)
            {
                Console.WriteLine(item);
                //Int32 id
            }
获取私有字段
            //获取私有字段
			FieldInfo[] NonPublicfields = t1.GetFields(BindingFlags.NonPublic|BindingFlags.Instance);
            foreach (var item in NonPublicfields)
            {
                Console.WriteLine(item);
                //Int32 iid
                //System.String<Name> k__BackingField //是public string Name { get; set; }中自动生成的私有字段
                //Int32<Age> k__BackingField
            }

Type.GetMethodsType.GetMethod 获取方法

获取所有方法
            MethodInfo[] methodInfos = t1.GetMethods();
            foreach (var item in methodInfos)
            {
                Console.WriteLine(item);
                /*
                 System.String get_Name()
                 Void set_Name(System.String)
                 Int32 get_Age()
                 Void set_Age(Int32)
                 Void SayHi()
                 System.Type GetType()
                 System.String ToString()
                 Boolean Equals(System.Object)
                 Int32 GetHashCode()
                */
            }
获取单个方法
            MethodInfo method = t1.GetMethod("SayHi");
            Console.WriteLine(method);//Void SayHi()

如果方法有重载

        public void SayHi()
        {
            Console.WriteLine($"大家好,我是{this.Name},我的年龄是{this.Age}");
        }

        public void SayHi(string name)
        {
        }

此时则会抛出异常

            MethodInfo method = t1.GetMethod("SayHi");
            Console.WriteLine(method);//Void SayHi()
//System.Reflection.AmbiguousMatchException:“Ambiguous match found.”--不明确匹配

此时则需要进行指定

            MethodInfo method = t1.GetMethod("SayHi",new Type[0]);
            Console.WriteLine(method);//Void SayHi()
            MethodInfo method1 = t1.GetMethod("SayHi", new Type[] {typeof(string)});
            Console.WriteLine(method1);//Void SayHi(System.String)

Type.GetProperties 方法 获取属性

            PropertyInfo[] props = t1.GetProperties();
            foreach (var item in props)
            {
                Console.WriteLine(item);
                //System.String Name
                //Int32 Age
            }

通过反射实例化对象与调用方法

    public class Person
    {
        public Person()
        {
        }
        public Person(string name)
        {
        }
        public int id;
        private int iid;
        public string Name { get; set; }
        public int Age { get; set; }
        public void SayHi()
        {
            Console.WriteLine($"大家好,我是{this.Name},我的年龄是{this.Age}");
        }

        public void SayHi(string name)
        {
            
        }
    }
        static void Main(string[] args)
        {
            Type type = typeof(Person);
            Object obj = Activator.CreateInstance(type);//调用无参构造函数
            PropertyInfo propName = type.GetProperty("Name");//获取该类的Name属性
            propName.SetValue(obj, "张三");//为对象obj的Name属性赋值“张三”
            PropertyInfo propAge = type.GetProperty("Age");
            propAge.SetValue(obj, 20);
            MethodInfo methodSayHi = type.GetMethod("SayHi", new Type[0]);
            methodSayHi.Invoke(obj, new object[0]);//通过Invoke(调用方法的对象,参数)来调用方法
                                                   //大家好,我是张三,我的年龄是20
            Console.WriteLine("-------------------------");
            //也可以通过直接调用构造函数的方法来实例化对象
            Type t = typeof(Person);
            Object obj2 = t.GetConstructor(new Type[0]).Invoke(new Object[0]);

            MethodInfo methodSayHi2 = t.GetMethod("SayHi", new Type[] { typeof(string) });
            methodSayHi2.Invoke(obj,new object[] {"fffffffff"});//obj2.SayHi("fffffffff")
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值