为什么我们需要反思呢?

时间:2018-05-08 02:11:13

标签: c# asp.net .net reflection system.reflection

我正在研究反思,我得到了一些,但我没有得到与这个概念相关的一切。为什么我们需要反思?我们无法实现哪些事情需要反思?

2 个答案:

答案 0 :(得分:17)

反射启用了许多场景,但我将它们主要分为两个桶。

  • Reflection使我们能够编写分析其他代码的代码

例如,考虑一个关于程序集的最基本问题:它中包含哪些类型?程序集是自描述,而反射是表示其他代码的机制。

假设您想编写一个程序,该程序接受程序集并对该程序集中各个类之间的关系进行图形显示,以帮助您理解该代码。有这样的工具。他们在Visual Studio中。 有人写过这些工具。他们没有通过魔法出现。反射是.NET框架中设计的机制,使您或我或任何其他人能够编写理解代码的工具。

  • Reflection使我们能够将编译时绑定移动到运行时。

假设您有一个静态方法Foo.Bar()。当您在程序中调用Foo.Bar()时,您可以100%确定地知道您认为将要调用的方法实际上将被调用。我们称之为静态方法"静态"因为从名称栏到被调用代码的绑定可以理解为静态 - 也就是说,不运行程序。

现在考虑基类上的虚方法Blah()。当您致电whatever.Blah()时,您并不确切知道在编译时将调用哪个Blah(),但您知道某些方法Blah()没有参数将在某些类型上调用,该类型是whatever的运行时类型,并且该类型等于或派生自声明Blah()的类型。 (事实上​​你知道更多:你知道它等于或衍生自whatever的编译时类型。)虚拟绑定是动态绑定的一种形式,但它不是完全动态。用户无法决定此调用应该是针对不同类型层次结构的不同方法。

Reflection允许我们在运行时进行完全绑定的调用,如果我们愿意的话,基于完全用户选择。我们支付了性能损失,并且我们失去了编译时类型的安全性,但我们可以灵活地在运行时决定100%我们调用的代码。在某些情况下,这是一个合理的权衡。

答案 1 :(得分:5)

反思是.NET框架的一个重要组成部分,您通常不知道自己在做什么(例如参见Attributes和LINQ)。当你确实知道自己在做这件事时,即使感觉不对,也可能是实现特定目标的唯一途径。

除了埃里克在这里提到的两个广泛领域之外还有其他一些领域。还有更多,这些只是立即想到的一些。

序列化(和类似的)

无论您是使用XML还是JSON还是自己滚动,当您不必为每个类编写特定代码以启用序列化时,序列化对象会更容易。 Reflection允许您枚举对象中已标记为(或未标记为)serailization的属性,并将它们写入输出。

这不是关于保存状态的。 Reflection允许我们编写可以生成业务输出的通用方法,例如来自任意集合的CSV或XLSX文件。我在ToCSV(...)ToExcel(...)扩展程序中获得了大量的里程数,例如在基于网络的报告中生成可下载的数据集版本。

访问隐藏数据

是的,我知道,这是一个狡猾的人。是的,Eric可能会为此拍打我,但是......

那里有很多代码 - 我在看着你,ASP.NET--它隐藏了privateprotected背后的有趣和有用的东西。有时,将它们取出的唯一方法是使用反射。有时它不是唯一的方式,但它可以是更简单的方式。

属性

每当您将Attribute标记到其中一个类,方法等上时,您隐式提供将通过反射访问的数据。想自己使用这些属性吗?反思是唯一可以解决问题的方法。

LINQ和其他表达式

这些日子真的很重要。如果您曾经使用过LINQ to SQL,实体框架等,那么您已经以某种方式使用了Expression。您编写了一个简单的小POCO来表示数据库表中的一行,其他所有内容都通过反射来处理。编写谓词表达式时,系统使用反射模型构建结构,然后处理(访问)以构建SQL语句。

表达式也不仅仅适用于LINQ,一旦你知道自己在做什么,你自己就会做一些非常有趣的事情。我有代码生成用于CSV导入的行解析器,当编译为Func<string, TRecord>时,它很快就运行得非常快。这些天我倾向于使用其他人写过的映射器,但当时我需要将具有20K记录的文件的总导入时间减少几个百分点,并定期上传到网站。

P / Invoke Marshalling

这个在幕后很重要,偶尔也在前台。当您想要调用Windows API函数或使用本机DLL时,P / Invoke为您提供了实现此目的的方法,而无需在两个方向上构建内存缓冲区。编组方法使用反射来对某些事物进行翻译 - 字符串等是明显的例子 - 这样你就不必弄脏手。所有这些都基于作为反思基础的Type对象。

事实上,没有反思,.NET框架就不会是它的本质。没有Attribute s,没有Expression s,语言之间的互通可能要少得多。没有自动编组。没有LINQ ......至少我们现在经常使用它。