C#进阶学习4--反射(Reflection)
2021-07-02 19:03
标签:http 设置 hone console 个数 名称 mamicode 方法 add 审查元数据并收集关于它的类型信息的能力。 (1)Assembly:定义和加载程序集,加载在程序集中的所有模块以及从此程序集中查找类型并创建该类型的实例。 在演示反射的作用之前,我们先定义如下实体类,假设该实体类位于一个第三方的类库下,类库名称为“TestClass”,类名为"Person" 创建不带成熟的对象,本质是就是调用无参的构造函数,具体实现如下 在控制台中调用 返回结果如下: 创建带成熟的对象,本质是就是调用带参数的构造函数,具体实现如下 在控制台中调用 返回结果如下: 利用反射调用第三方类的方法,可以通过反射得到对应的对象之后,利用得到的对象来执行对象中的方法,但是在这里,主要讲解通过反射,直接调用第三方类中的方法,具体实现如下 在控制台中调用 返回结果如下: 在控制台中调用 返回结果如下: 下面写一个综合的例子,调用Person类中的所有方法,并输出结果,如果参数类型为String,则默认传"AAA",如果参数类型为Int,则默认传666,实现方法如下: 调用后返回结果如下: 调用后返回结果如下: 调用后返回结果如下: 调用后返回结果如下: 接下来,我们继续研究反射在泛型中的作用,在进一步研究之前,我们先定义如下泛型类,同以上实体类一样,假设该泛型类位于一个第三方的类库下,类库名称为“TestClass”,类名为"GenericClass" 调用后返回结果如下: 至此,反射的常用方式讲解完毕... C#进阶学习4--反射(Reflection) 标签:http 设置 hone console 个数 名称 mamicode 方法 add 原文地址:https://www.cnblogs.com/zykj/p/14957416.html一.反射的定义
二.基础概念
(2)Module:获取包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)ConstructorInfo:获取构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(4)MethodInfo(GetMethod/GetMethods):获取方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(5)FiedInfo(GetField/GetFields):获取字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)EventInfo(GetEvent/GetEvents):获取事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)PropertyInfo(GetProperty/GetProperties):获取属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
(8)ParameterInfo:获取参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
(9)MemberInfo(GetMember/GetMembers):获取字段、事件、属性等各种信息三.反射作用
public class Person
{
private int id;
public int Id { get => id; set => id = value; }
public string Name { set; get; }
public string Phone { get; set; }
public Person()
{
}
public Person(string a, int b)
{
this.Name = a;
this.Phone = b.ToString();
}
public Person(int id, string name, string phone)
{
this.Id = id;
this.Name = name;
this.Phone = phone;
}
public string getName()
{
return this.Name;
}
public string getName1(string str)
{
return str;
}
public string getPhone()
{
return this.Phone;
}
public string getPhone(string str)
{
return this.Phone+str;
}
public string getPhone(string str,int num)
{
return this.Phone + str+num;
}
private void privateMethod(string a)
{
Console.WriteLine("这是一个私有方法,传入的参数是:"+a);
}
}
1.创建不带参数的对象
///
Person person = CreateWithoutParms();
person.Name = "张三";
Console.WriteLine("person.Name:"+ person.Name);
成功调用了创建了Person,并调用了Person的无参构造方法2.创建带参数的对象
///
Person person = CreateWithParms();
Console.WriteLine("person.Name:"+person.Name+ " person.Phone:" + person.Phone);
成功调用了创建了Person,并利用带参数的构造直接给属性赋值说明:如果构造函数为私有的,可以在创建实例时,将CreateInstance中的nonPublic参数设置为true,即可使用私有的构造函数创建实例
object o = Activator.CreateInstance(type,true);
3.调用公共方法
///
string rsult = CallFunction();
Console.WriteLine(rsult);
在这里我们看到,利用反射成功调用了getName1方法,需要注意的是,getName1方法并没有任何重载,如果需要调用带有重载的方法,需要用下面的方法,这里我们假设需要调用getPhone(string str,int num)方法 private static string CallFunctionWithOverload()
{
Assembly assembly = Assembly.Load("TestClass");
Type type = assembly.GetType("TestClass.Person");
object o = Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod("getPhone", new Type[] { typeof(string), typeof(int) });//在这里需要把参数类型数组传递给GetMethod方法
string result=methodInfo.Invoke(o, new object[] { "这是传入的String参数", 666 }).ToString();
return result;
}
string rsult = CallFunctionWithOverload();
Console.WriteLine(rsult);
通过以上的例子,我们可以看到,调用有重载和无重载方法的关键,就是在GetMethod中是否传递参数的类型。
private static void CallAllFunction()
{
Assembly assembly = Assembly.Load("TestClass");
Type type = assembly.GetType("TestClass.Person");
object o = Activator.CreateInstance(type);
foreach (MethodInfo methodInfoItem in type.GetMethods())
{
Console.WriteLine("执行"+ methodInfoItem.Name+ "方法");
List
在这里我们看到,Person中的方法已经全部执行,包括所有的系统方法4.调用私有方法
///
通过以上例子,我们不难发现,调用公共方法与私有方法的区别就是在调用type的GetMethod方法时,是否设置"BindingFlags.Instance | BindingFlags.NonPublic"
5.获取与操作属性
///
通过以上例子,可以发现,获取与设置属性的关键方法分别为GetValue与SetValue,关键传入参数为通过反射得到的实体类
6.获取与操作字段
///
设置和操作字段的方法与设置和操作属性的方法基本一直,需要注意的是,在用type的GetField方法时,如果获取或设置的是私有字段,需要设置该方法的可访问属性,本例中的设置为"BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance"
public class GenericClass
7.创建泛型类并调用
///
针对以上代码,做出以下几点说明:
1).
只有在创建泛型类时,才需要做这样的设置,数字为泛型类总参数的个数
2).
在创建泛型实体之前,要通过type的MakeGenericType方法,设置传入的参数类型
3).
同创建泛型类一样,在调用泛型方法前,也需要设置泛型方法的参数类型
4).如果调用的是泛型类中的普通方法,无需设置泛型方法的参数类型,反之,如果调用的是普通类中的泛型方法,无需设置泛型类参数个数,也无需设置参数类型
上一篇:打印选择菜单,一键安装Web服务
下一篇:C# Async Streams