反射与动态关键字的实用指南

在编程世界中,动态操作对象的能力是一个强大而灵活的工具。本文将深入探讨两个关键概念:反射(Reflection)和动态关键字(dynamic)。许多开发者对这两个概念感到困惑,因为它们都能实现动态调用。本文旨在揭示它们之间的区别,并探讨在何种场景下使用它们。但在比较之前,先分别理解每一个概念,然后在文章的最后进行全面比较。

什么是反射以及为什么需要它?

当想要确定或检查一个程序集的内容时,就需要使用反射。例如,当在Visual Studio编辑器中输入对象前的“.”(点)时,它会给显示对象的所有成员。这正是反射的作用。反射还可以进一步操作,它可以在运行时调用检查到的成员。例如,如果反射检测到对象中有一个名为GetChanges的方法,可以在运行时获取该方法的引用并调用它。

简而言之,反射包括两个步骤:“检查”和“调用”(可选)。“调用”过程是可选的。

如何实现反射?

在C#中实现反射是一个两步过程:首先获取对象的“类型”,然后使用该类型浏览成员,如“方法”、“属性”等。

第一步是获取对象的类型。例如,有一个名为ClassLibrary1.dll的DLL,其中包含一个名为Class1的类。可以使用属于System.Reflection命名空间的Assembly类来获取对象类型的引用。之后,可以使用Activator.CreateInstance来创建类的实例。GetType()函数帮助获取对象类型的引用。

var myAssembly = Assembly.LoadFile("C:\\ClassLibrary1.dll"); var myType = myAssembly.GetType("ClassLibrary1.Class1"); dynamic objMyClass = Activator.CreateInstance(myType); // 获取类类型 Type parameterType = objMyClass.GetType();

一旦有了对象类型的引用,就可以调用GetMembers()或GetProperties()来浏览类的成员。

// 浏览成员 foreach (MemberInfo objMemberInfo in parameterType.GetMembers()) { Console.WriteLine(objMemberInfo.Name); } // 浏览属性 foreach (PropertyInfo objPropertyInfo in parameterType.GetProperties()) { Console.WriteLine(objPropertyInfo.Name); }

如果想调用已经检查过的成员,可以使用InvokeMember来调用方法。以下是代码:

parameterType.InvokeMember("Display", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod | BindingFlags.Instance, null, objMyClass, null);

反射的实际用途是什么?

如果正在创建一个像Visual Studio编辑器这样的应用程序,希望使用智能感知显示对象的内部结构。如果正在创建一个单元测试框架。在单元测试框架中,需要动态地调用方法和属性以进行测试。有时希望将属性、方法和程序集引用转储到文件中或显示在屏幕上。

动态关键字的用途是什么?

编程语言可以分为两类:强类型和动态类型。强类型语言是在编译时进行检查的,而动态语言是在编译时绕过类型检查的。在动态语言中,对象类型只有在运行时才知道,类型检查只在运行时激活。

希望同时利用这两个世界的优势。因为很多时候,直到代码执行时才知道对象类型。换句话说,正在寻找一种动态和静态类型环境的结合。这就是动态关键字帮助地方。

如果使用动态关键字创建一个变量,如果尝试查看该对象的成员,将得到以下消息:“将在运行时解析”。

dynamic x = "c#"; x++;

现在这段代码将在没有任何抱怨的情况下编译。但在运行时,它将抛出一个异常,抱怨不能在变量上执行数学操作,因为它是一个字符串类型。换句话说,在运行时,动态对象从一般数据类型转换为特定数据类型(例如:下面的代码中的字符串)。

动态关键字的实际用途是什么?

动态关键字最大的实际用途之一是通过互操作操作MS Office组件时。例如,如果不使用动态关键字访问Microsoft Excel组件,可以看到代码变得多么复杂。下面有很多强制转换,对吧?

Application excelApplication = new Application(); ((Excel.Range)excelApp.Cells[1, 1]).Value2 = "Name"; Excel.Range range2008 = (Excel.Range)excelApp.Cells[1, 1];

现在看看使用动态关键字后代码变得多么简单。不需要强制转换,运行时类型检查也发生了。

dynamic excelApp = new Application(); excelApp.Cells[1, 1].Value = "Name"; Excel.Range range2010 = excelApp.Cells[1, 1];

反射和动态之间的区别是什么?

当想要在运行时操作对象时,都会使用反射和动态。反射用于检查对象的元数据。它还可以在运行时调用对象的成员。动态关键字是在.NET 4.0中引入的。它在运行时评估对象调用。所以在方法调用之前,编译器并不关心这些方法/属性是否存在。

动态使用反射内部。它缓存了所做的方法调用,从而在一定程度上提高了性能。反射可以调用对象的公共和私有成员,而动态只能调用公共成员。动态是实例特定的:无法访问静态成员;在这些情况下,必须使用反射。

下面是一个详细的比较表,显示了它们在哪种场景下适用:

反射 动态
检查(元数据)
调用公共成员
调用私有成员
缓存
静态类

以下是一个简单的图表,总结了反射能做什么以及动态关键字能做什么。

对于进一步阅读,请观看以下面试准备视频和逐步视频系列:

  • C#面试问题及答案
  • ASP.NET MVC 面试问题及答案
  • Angular 面试问题及答案
  • 逐步学习Azure
  • 逐步学习SQL Server
  • C#抽象类与接口
  • C# is与as关键字
  • C#Throw与Throw ex
  • C# 并发与并行
  • C# 字符串是不可变的
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485