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

简介: 【.NET Core】反射(Reflection)详解(三)

一、概述

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


二、ConstructorInfo类

使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等

Type type = typeof(ReflectionCLS);
ConstructorInfo constructorInfo= type.GetConstructor(new Type[] { typeof(string)});
ReflectionCLS reflection  =(ReflectionCLS) constructorInfo.Invoke(new object[] {"No" });
string no = reflection.No;
Console.WriteLine(no);
ConstructorInfo constructor1=type.GetConstructor(new Type[] { typeof(string) ,typeof(string)});
ReflectionCLS reflections = (ReflectionCLS)constructor1.Invoke(new object[] { "No1", "Code" });
no = reflections.No;
string code = reflections.Code;
Console.WriteLine(no);
Console.WriteLine(code);

2.1 ConstructorInfo.MemberType 属性

获取MemberTypes值,该值指示此成员是构造函数。

2.2 ConstructorInfo.Invoke 方式

调用反射后的构造函数,初始化类


三、MethodInfo类

发现方法的属性并提供对方法元数据的访问。MethodInfo类表示类型的方法。你可以使用MethodInfo对象获取有关对象所表示的方法的信息,以及调用方法。比如:

  • 可以通过检索IsFamilyAndAssembly、IsFamilyOrAssembly、IsPrivate和属性的值来确定该方法的可见性IsPublic。
  • 可以通过检索属性的值Attributes或调用方法来发现应用于方法的特性GetCustomAttributes。
  • 通过检索和属性的值,可以确定方法是泛型方法,开放式构造泛型方法还是封闭式构造泛型方法IsGenericMethod、ContainsGenericParameters。
  • 可以从GetParameters方法和ReturnParameter、ReturnType和属性获取有关方法的参数和返回类型的信息。
  • 可以通过调用方法对类实例执行方法Invoke。
  • 通过调用方法。可以实例化MethodInfo表示泛型方法定义的构造泛型方法的对象MakeGenericMethod。

3.1 获取MethodInfo的方法

  1. Type.GetMethod(String)获取该类的指定的名称String公开的函数方法。如果方法为私有则返回为Null。
  2. Type.GetMethod(String,BindingFlags)获取该类的指定的名字String和指定类型BindingFlags的函数方法。
  3. Type.GetMethods() 获取该类的所有公共的函数方法。
  4. Type.GetMethods(BindingFlags)获取该类的所有指定类型BinddingFlags的函数方法。

3.2 MethodInfo常用属性

  • MethodInfo.MemberInfo属性
    只读属性获取一个MemberTypes值,该值指示成员是方法。
  • MethodInfo.ReturnParameter属性
    获取一个ParameterInfo对象,该对象包含有关方法的返回类型的信息。
  • MethodInfo.ReturnType属性
    获取此方法的返回类型。
  • MethodInfo.ReturnTypeCustomAttributes属性
    获取返回类型的自定义属性。

3.3 MethodInfo常用方法

  • MethodInfo.GetBaseDefinition方法
    当在派生类中被重写时,为直接或间接的基类(用该实例表示的方法首先在此类中声明)上的方法返回MethodInfo对象。
Type type = Type.GetType("GoyeerConsoleAssertApp.Entity.MachineDemo");
MethodInfo memberInfo = type.GetMethod("Method1");
MethodInfo mb = memberInfo.GetBaseDefinition();
Console.WriteLine($"{memberInfo.ReflectedType.FullName}父类方法{mb.ReflectedType.FullName}");

输出结果

AwinicConsoleAssertApp.Entity.MachineDemo父类方法AwinicConsoleAssertApp.Entity.BaseClass

MethodInfo.GetGenericArguments方法

返回Type对象的数组,这些对象表示泛型方法的类型实参或泛型方法定义的类型形参。

Type type = Type.GetType("GoyeerConsoleAssertApp.Entity.MachineDemo");
MethodInfo memberInfo = type.GetMethod("Method1");
Type[] types = memberInfo.GetGenericArguments ();
foreach (Type tParam in types) 
{
    if (tParam.IsGenericTypeParameter) 
    {
          Console.WriteLine("\t\t{0}  parameter position {1}" +
               "\n\t\t   declaring method: {2}",
          tParam,
          tParam.GenericParameterPosition,
          tParam.DeclaringMethod);
    }
}

返回数组的元素按它们在泛型方法的类型参数列表中出现的顺序排列


1、如果当前方法是封闭的构造方法(既GetGenericArguments属性返回false),则该方法返回GetGenericArguments的数组包含已分配给泛型方法定义的泛型类型参数的类型。


2、如果当前方法是泛型方法定义,则数组包含类型参数。


3、如果当前方法是打开的构造方法,其中特定类型已分配给某些类型参数,而封闭泛型类型的类型参数已分配给其他类型参数,则数组同时包含类型和类型参数。

MethodBase.GetParameters方法

当在派生类中重写时,获取指定的方法的参数。

返回值 ParameterInfo[]

ParameterInfo类型的数组,包含与此MethodBase实例所反射的方法签名匹配的信息。

Type type = Type.GetType("GoyeerConsoleAssertApp.Entity.MachineDemo");
MethodInfo memberInfo = type.GetMethod("Method1");
ParameterInfo[] parameterInfos = memberInfo.GetParameters ();
foreach (ParameterInfo parameter in parameterInfos) 
{
    Console.WriteLine(parameter.Name);  
}

MethodBase.Invoke 方法

调用由此MethodInfo实例反射的方法或构造函数。

1、Invoke(Object,Object[]) 使用指定参数调用由当前实例表示的方法或构造函数。

参数一 Object: 在其上调用方法或构造函数的对象。如果方法是静态的,则忽略此参数。如果构造函数是静态的,则此参数必须是null或定义构造函数的类的实例。


参数二 Object[] 调用方法或构造函数的参数列表。此对象数组在数量、顺序和类型方面与要调用的方法或构造函数的参数相同。如果不存在任何参数,则parameters应为null。

返回值 Object 一个包含已调用方法的返回值或包含已调用构造函数的null的对象。

Type type = Type.GetType("GoyeerConsoleAssertApp.Entity.MachineDemo");
//在其上调用方法或构造函数的对象
ConstructorInfo magicConstructor = type.GetConstructor(Type.EmptyTypes);
object magicClassObject = magicConstructor.Invoke(new object[] { });
MethodInfo memberInfo = type.GetMethod("Method1");
//多用参数集合
memberInfo?.Invoke(magicClassObject, new object[] { "Param1", "Param2", "Param3", 40 });

2、Invoke(Object,BindingFlags,Binder,Object[],CultureInfo) 当在派生类中重写时,调用具有给定参数的反射的方法或构造函数。

参数

obj Object


在其上调用方法或构造函数的对象。如果方法是静态的,则忽略此参数。如果构造函数是静态,则此参数必须是null或定义构造函数的类的实例。


invokeAttr BindingFlags


位屏蔽,它是BindingFlags的0个或多个位标志的组合。如果binder为null,则此参数赋值为Default;因此,传入的任何值都被忽略。


binder Binder


一个对象,它启用绑定、对自变量类型的强制、对成员的调用,以及通过反射对MemberInfo对象的检索。如果binder为null,则使用默认联编程序。


parameters Object[]


调用方法或构造函数的参数列表。此对象数组在数量、顺序和类型方面与要调用的方法或构造函数的参数相同。如果没有参数,则此应为null。


如果此实例表示的方法或构造函数采用 ByRef 参数,那么使用此函数调用该方法或构造函数时,对于该参数不需要特殊的特性。 此数组中未使用值显式初始化的任何对象都将包含该对象类型的默认值。 对于引用类型元素,此值为null。


culture CultureInfo


用于控制类型强制CultureInfo的实例。如果这是null,则使用当前线程的CultureInfo。


返回


object,包含被调用方法的返回值;如果调用的是构造函数,则为null;如果方法的返回类型是null,则为void在调用方法或构造函数之前,Invoke检查用户是否有访问权限并验证参数是否有效。


四、FieldInfo类

发现字段的属性并提供对字段元数据的访问权限。字段信息是从元数据获取的。类FieldInfo没有公共构造函数。FieldInfo对象是通过调用GetFields对象的或GetField方法获取的Type。字段是在类中定义的变量。FieldInfo提供对类中字段元数据的访问,并为字段提供动态集和获取功能。在对象上调用invoke或get之前,类不会加载得到内存中。


4.1 获取FieldInfo类方法

  • GetField(string) 获取当前Type的特定字段。
  • GetFields() 获取FieldInfo集合。
Type type = Type.GetType("AwinicConsoleAssertApp.Entity.MachineDemo");
FieldInfo fieldInfo = type.GetField("FieldA");
Console.WriteLine($"FieldInfo={fieldInfo.Name}");
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
    Console.WriteLine($"FieldInfo的Name={field.Name}");
}

4.2 FieldInfo常用属性

  • IsPrivate 获取一个值,通过该值指示此字段是否为私有字段。
  • IsPublic 获取一个值,通过该值指示此字段是否为公共字段。
  • IsStatic 获取一个值,通过该值指示此字段是否为静态字段。
  • Name 获取当前成员的名称。


4.3 FieldInfo常用方法

  • FieldInfo.GetValue(Object)方法
    当在派生类中重写时,返回给定对象支持的字段的值。
FieldInfo fld = typeof(Example).GetField("val");
Console.WriteLine(fld.GetValue(null));
val = "hi";
Console.WriteLine(fld.GetValue(null));

FieldInfo.SetValue(Object?,Object?)方法

将给定对象的字段值设置为给定值。

Example myObject = new Example();
Type myType = typeof(Example);
FieldInfo myFieldInfo = myType.GetField("myString",BindingFlags.NonPublic | BindingFlags.Instance);
Console.WriteLine($"The field value of myString is {myFieldInfo.GetValue(myObject)}.");
myFieldInfo.SetValue(myObject, "New value");
Console.WriteLine($"The field value of mystring is myFieldInfo.GetValue(myObject).");

五、PropertyInfo类

发现属性(Property)的属性(Attribute)并提供对属性(Property)元数据的访问。

5.1 获取PropertyInfo类方法

  • GetProperty(string) 返回:PropertyInfo System.Type 实例,表示当前实例的确切运行时类型。
  • GetProperties() 返回: PropertyInfo[] 表示当前 System.Type 的所有公共属性的 System.Reflection.PropertyInfo 对象数组。


或 -如果当前 System.Type 没有公共属性,则为 System.Reflection.PropertyInfo 类型的空数组。

5.2 PropertyInfo主要属性

  • CanRead
    获取一个值,该值指示是否可读属性。
  • CanWrite
    获取一个值,该值指示是否可写属性。
  • GetMethod
    获取属性的Get访问器
Type MyTypea = Type.GetType("Mypropertya");
PropertyInfo Mypropertyinfoa = MyTypea.GetProperty("Caption");
Type MyTypeb = Type.GetType("Mypropertyb");
PropertyInfo Mypropertyinfob = MyTypeb.GetProperty("Caption");
 // Get and display the CanWrite property.
Console.Write("\nCanWrite a - " + Mypropertyinfoa.CanRead);
Console.Write("\nCanWrite b - " + Mypropertyinfob.CanWrite);

5.3 PropertyInfo主要方法

  • PropertyInfo.GetValue 方法
    返回指定对象的属性值。
  • PropertyInfo.SetValue 方法
    设置指定对象的属性值。
string test = "abcdefghijklmnopqrstuvwxyz";
PropertyInfo pinfo = typeof(string).GetProperty("Chars");
for (int x = 0; x < test.Length; x++)
{
    Console.Write(pinfo.GetValue(test, new Object[] {x}));
}
 Console.WriteLine();


五、总结

程序通过类创建对象,反射将这一过程进行反转,通过实例化对象来获取所属类的信息。


作用:在程序运行状态时,构造任意一个类的对象、获取任意一个对象所属的类的信息、调用任意一个类的成员变量和方法、获取任意一个对象的属性和方法。


优点:可以在程序运行期间动态的创建和编译对象,不需要再次重新编译,就可以更新。

目录
相关文章
|
2月前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
3月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
100 3
|
2月前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
3月前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
3月前
|
C#
在.NET Core中灵活使用反射
在.NET Core中灵活使用反射
|
4月前
|
开发框架 监控 .NET
开发者的革新利器:ASP.NET Core实战指南,构建未来Web应用的高效之道
【8月更文挑战第28天】本文探讨了如何利用ASP.NET Core构建高效、可扩展的Web应用。ASP.NET Core是一个开源、跨平台的框架,具有依赖注入、配置管理等特性。文章详细介绍了项目结构规划、依赖注入配置、中间件使用及性能优化方法,并讨论了安全性、可扩展性以及容器化的重要性。通过这些技术要点,开发者能够快速构建出符合现代Web应用需求的应用程序。
58 0
|
4月前
|
缓存 数据库连接 API
Entity Framework Core——.NET 领域的 ORM 利器,深度剖析其最佳实践之路
【8月更文挑战第28天】在软件开发领域,高效的数据访问与管理至关重要。Entity Framework Core(EF Core)作为一款强大的对象关系映射(ORM)工具,在 .NET 开发中扮演着重要角色。本文通过在线书店应用案例,展示了 EF Core 的核心特性和优势。我们定义了 `Book` 实体类及其属性,并通过 `BookStoreContext` 数据库上下文配置了数据库连接。EF Core 提供了简洁的 API,支持数据的查询、插入、更新和删除操作。
117 0
|
4月前
|
开发框架 监控 .NET
【Azure 应用程序见解】在Docker中运行的ASP.NET Core应用如何开启Application Insights的Profiler Trace呢?
【Azure 应用程序见解】在Docker中运行的ASP.NET Core应用如何开启Application Insights的Profiler Trace呢?
|
4月前
|
Linux C# C++
【Azure App Service For Container】创建ASP.NET Core Blazor项目并打包为Linux镜像发布到Azure应用服务
【Azure App Service For Container】创建ASP.NET Core Blazor项目并打包为Linux镜像发布到Azure应用服务

热门文章

最新文章

下一篇
无影云桌面