【.NET Core】反射(Reflection)详解(二)

一、概述

反射提供了对已封装的程序集、模型和类型的对象一种动态访问方法。反射包含动态加载程序集的Assembly类、程序集中模块访问的Module类、对类信息Type类、构造函数信息ConstructorInfo类、方法信息MethodInfo类、字段信息FieldInfo类、事件信息EventInfo类、属性信息PropertyInfo类、参数信息ParameterInfo类。博文《》已详细讲解了Assembly类、Module类的用法。本章将重点讲解Type类

二、Type类

Type类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义以及开发或封闭构造的泛型类型。

Type是功能的根类。System.Relection是访问元数据的主要方式。使用的成员Type获取有关类型声明、类型的构造函数、方法、字段、属性和事件以及在其中部署类的模块和程序集。Type无需任何权限即可通过反射获取有关类型及其成员信息。

2.1 Type对象表示哪些类型

此类是线程安全的,多个线程可以并发读取此类型的实例。类Type实例可以表示以下任一类型:

  • 值类型
  • 数组
  • 接口
  • 枚举
  • 委托
  • 构造泛型类型和泛型类型定义
  • 构造泛型类型、泛型类型定义和泛型方法定义的类型参数和类型参数

2.2 获取Type及其关联对象类型的方式

  • 实例化对象通过Object.GetType方法返回一个Type对象,该对象表示实例化类型。由于Object是所有托管类型的基类,因此任何类型的实例都可以调用GetType方法。

    StringHelper stringHelper= new StringHelper();       
    Type type= typeof(StringHelper);
    String str = new String("abdce")
    Type type1 =  str.GetType();
    
  • 静态typeof()返回一个Type对象,该对象表示由其完全限定名称指定的类型。

    Type typeHelper= typeof(StringHelper);
    Type typeString = typeof(String);
    

2.3 Type.FilterName字段

表示用于名称的区分大小写的成员筛选器,此字段为只读。此字段对方法使用的委托的FindMembers引用。此委托封装的方法采用两个参数:第一个MemberInfo是对象,第二个Object是确定匹配条件。Object分配了一个字符串值,可使用通配符(*),这个通配符仅支持结束字符串匹配。

Type typeHelper = typeof(StringHelper);
MemberInfo[] members = typeHelper.FindMembers(MemberTypes.Constructor|
                                              MemberTypes.Method,
                                              BindingFlags.Public    |
                                              BindingFlags.Static    |
                                              BindingFlags.NonPublic |
                                              BindingFlags.Instance  |
                                              BindingFlags.DeclaredOnly,
                                              Type.FilterName, 
                                              "GetStr*");

2.4 Type.FilterNameIgnoreCase字段

表示用于名称的不区分大小写的成员筛选器。此字段为只读。此字段对方法使用的委托的FindMembers引用。此委托封装的方法采用两个参数:第一个MemberInfo是对象,第二个Object是MemberInfo与指定的Object条件是否匹配。Object与Type.FilterName一样,分配了一个统配了一个字符串值,其中可包含结尾通配符(*);

Type typeHelper = typeof(StringHelper);
MemberInfo[] members = typeHelper.FindMembers(MemberTypes.Constructor|
                                              MemberTypes.Method,
                                              BindingFlags.Public    |
                                              BindingFlags.Static    |
                                              BindingFlags.NonPublic |
                                              BindingFlags.Instance  |
                                              BindingFlags.DeclaredOnly,
                                              Type.FilterName, 
                                              "getstr*");

2.5 Type.Assembly属性

获取在其中声明该类型的Assembly,对于泛型类型、则获取在其中定义该泛型类型的Assembly。

Type typeHelper = typeof(StringHelper);
Console.WriteLine($"Assembly full name:{typeHelper.Assembly.FullName}");
Console.WriteLine($"Assembly QualifiedName:{typeHelper.Assembly.AssemblyQualifiedName}");

2.6 Type.BaseType属性

获取当前Type直接从中继承的类型。

Type t = typeof(int);
Console.WriteLine($"int inherits from {t.BaseType}");

2.7 Type.FullName属性

获取当前Type的名称,包含namespace但是不包含Assembly

Type t = typeof(int);
Console.WriteLine($"int inherits from {t.FullName}");

2.8 Type.Module属性

获取在其中定义当前Type的模块(DLL)

Type typeHelper = typeof(int);
Console.WriteLine($"Module QualifiedName:{typeHelper.Module.FullyQualifiedName}");

显示内容

Module QualifiedName:C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.3\System.Private.CoreLib.dll

2.9 Type.Namespace属性

获取当前命名空间,如果当前Type没有命名空间或表示泛型的参数,则为空。

Type typeHelper = typeof(int);
Console.WriteLine($"The Namespace:{type.Namespace}");

2.10 Type.FindMembers方法

返回指定成员类型的MemberInfo对象的筛选数组。

参数MemberTypes

2.11 Type.GetConstructor方法

用指定绑定约束和指定调用约束,搜索其参数与指定参数类型及修饰符匹配的构造函数。

public System.Reflection.ConstructorInfo? GetConstructor (System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder? binder, System.Reflection.CallingConventions callConvention, Type[] types, System.Reflection.ParameterModifier[]? modifiers);

参数

bindingAttr BindingFlags

枚举值的按位组合,这些值指定如何进行搜索 BindingFlags枚举参考

binder Binder

一个对象,该对象定义一组属性并启用绑定,而绑定可能涉及选择重载方法,强制参数类型和通过反射调用成员。

callConvention CallingConventions

对象,用于指定要使用的一套规则,这些规则涉及参数的顺序和布局、传递返回值的方式,用于参数的寄存器和清理堆栈的方式。

type Type[]

Type对象的数组,表示构造函数要获取的参数的个数,顺序和类型。

modifiers ParameterModifier[]

ParameterModifier对象的数组,表示与types数组中的相应元素关联的特性。

返回

ConstructorInfo

表示符合指定需求的构造函数的对象;否则为null

2.12 Type.GetField 方法

获取当前Type的特定字段

GetField(String) : 搜索具有指定名称的公共字段。

GetField(String,BindingFlags) : 使用指定绑定约束搜索指定字段。

Type myTypeA = typeof(MyFieldClassA);
FieldInfo myFieldInfo = myTypeA.GetField("Field");

2.13 Type.GetMember方法

获取当前类型的指定成员。

GetMember(String) : 搜索具有指定名称的公共成员

GetMember(String,BindingFlags) : 使用指定的绑定约束搜索指定成员

GetMember(String,MemberTypes,BindingFlags) : 使用指定的绑定约束搜索指定成员类型的指定成员。

String myString = "GetMember_String";
Type myType = myString.GetType();
MemberInfo[] myMembers = myType.GetMember("C*");

2.14 Type.GetMethod 方法

获取当前Type的特定方法。

GetMethod(String,Int32,BindingFlags,Binder,CallingConventions,Type[],ParameterModifier[])

使用指定的绑定约束和指定的调用约定搜索其参数与指定泛型参数计数、参数类型及修饰符匹配的指定方法。

GetMethod(String, BindingFlags, Binder, CallingConventions, Type[], ParameterModifier[])

用指定的绑定约束和指定的调用约定,搜索参数与指定的参数类型及修饰符相匹配的指定方法。

GetMethod(String,Int32,BindingFlags,Binderm,Type[],ParameterModifier[])

使用指定绑定约束,搜索其参数与指定泛型参数计数、参数类型及修饰符匹配的指定方法。

GetMethod(String)

搜索具有指定名称的公共方法

StringHelper stringHelper = new StringHelper();
Type type = typeof(StringHelper);
var methodInfos = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
MethodInfo methodInfo= methodInfos?.First();
Console.WriteLine($"The methodInfo :{methodInfo.Name}");

2.15 Type.GetProperty 方法

获取当前Type的特定属性。

  • GetProperty(String,Type,Type[])

    搜索其参数与指定自变量类型匹配的指定公共属性。

  • GetProperty(String,BindingFlags,Binder,Type,Type[],ParameterModifier[])

    使用指定的绑定约束,搜索参数与指定的自变量类型及修饰符匹配的指定属性。

  • GetProperty(String,Type,Type[],ParameterModifier[])

    搜索其参数与指定自变量类型及修饰符匹配的指定公共属性

  • GetProperty(String,Type[])

    搜索其参数与指定自变量类型匹配的指定公共属性

  • GetProperty(String,Type)

    搜索具有指定名称和返回类型的公共属性

  • GetProperty(String)

    搜索具有指定名称的公共属性

2.16 Type.InvokeMember方法

调用当前Type的特定成员。

  • InvokeMember(String,BindingFlags,Binder,Object,Object[])

    使用指定的绑定约束并匹配指定的参数列表,调用指定成员。

  • InvokeMember(String,BindingFlags,Binder,Object,Object[],CultureInfo)

    使用指定的绑定约束和匹配的指定参数列表及区域性来调用指定成员。

  • InvokeMember(String,BindingFlags,Binder,Object,Object[],ParameterModifier,CultureInfo,String)

    当在派生类中重写时,使用指定的绑定约束并匹配指定的参数列表、修饰符和区域性,调用指定成员。

参数

name String

字符串,它包含要调用的构造函数、方法、属性或字段成员的名称。或空字符串(“”),表示调用默认成员。

invokeAttr BindingFlags

枚举值的按位组合,这些值指定如何进行搜索。访问可以是BindingFlags之一。如 PublicNonPublicPrivateInvokeMethodGetField 等。 查找类型无需指定。 如果省略查找的类型,则将使用 BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static

binder Binder

一个对象,该对象定义一组属性并启用绑定,而绑定可能涉及选择重载方法、强制参数类型和通过反射调用成员。

target Object

对其调用指定成员的对象。

args Object[]

包含传递给要调用的成员的参数数组。

StringHelper stringHelper = new StringHelper();
Type type = typeof(StringHelper);
Object obj = type .InvokeMember(null,
             BindingFlags.DeclaredOnly |
             BindingFlags.Public | BindingFlags.NonPublic |
             BindingFlags.Instance | BindingFlags.CreateInstance, null, null, args);
var methodInfos = type.GetMethod("RemoveLastChar");
 object response =   type.InvokeMember("RemoveLastChar", 
                     BindingFlags.DeclaredOnly |
                     BindingFlags.Public | 
                     BindingFlags.NonPublic |
                     BindingFlags.Instance | 
                     BindingFlags.InvokeMethod, null, obj, 
                     new Object[] { "This is ,水电费," ,","});
 Console.WriteLine($"The methodInfo :{response}");

二、总结

System.Type类是一个抽象的基类,实例化Type对象,其实就是实例化Type的一个派生类。Type是许多反射功能的入口。

12-23 18:11