反射
反射可以做什么?
动态创建对象
动态赋值
动态调用方法
反射简介
.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
通过反射动态创建对象
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 属性
获取当前Type对象的对应类名
获取当前Type对象的对应完整类名(命名空间.类名)
Type t1 = typeof(Person);
Console.WriteLine(t1.Name);//Person
Console.WriteLine(t1.FullName);//ConsoleApp2.Person
Type.GetConstructor ,Type.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.GetMethods 和Type.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")
}

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

被折叠的 条评论
为什么被折叠?



