C# 为什么我们需要反思?

C# 为什么我们需要反思?,c#,asp.net,.net,reflection,system.reflection,C#,Asp.net,.net,Reflection,System.reflection,我在研究反思,我得到了一些,但我没有得到与这个概念相关的一切。为什么我们需要反思?什么事情我们不能实现,我们需要反射?反射可以实现很多很多场景,但我主要将它们分为两个部分 反射使我们能够编写分析其他代码的代码 例如,考虑有关程序集的最基本问题:程序集中有哪些类型?程序集是自描述的,反射是将该描述呈现给其他代码的机制 例如,假设您想编写一个程序,它接受一个程序集,并以图形方式显示该程序集中各个类之间的关系,以帮助您理解该代码。有这样的工具。他们在Visual Studio中那些工具是有人写的。

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

反射可以实现很多很多场景,但我主要将它们分为两个部分

  • 反射使我们能够编写分析其他代码的代码
例如,考虑有关程序集的最基本问题:程序集中有哪些类型?程序集是自描述的,反射是将该描述呈现给其他代码的机制

例如,假设您想编写一个程序,它接受一个程序集,并以图形方式显示该程序集中各个类之间的关系,以帮助您理解该代码。有这样的工具。他们在Visual Studio中那些工具是有人写的。它们不是靠魔法出现的。反射是在.NET framework中设计的一种机制,它使您、我或任何其他人都能够编写理解代码的工具

  • 反射使我们能够将编译时绑定移动到运行时
假设您有一个静态方法
Foo.Bar()
。当您在程序中调用
Foo.Bar()
时,您100%肯定地知道您认为将要调用的方法实际上将被调用。我们称静态方法为“static”,因为从名称栏到被调用代码的绑定可以静态地理解——也就是说,无需运行程序

现在在基类上考虑一个虚拟方法<代码> BLHAH()/<代码>。当您调用

whater.Blah()
时,您并不确切知道编译时将调用哪个
Blah()
,但是您知道,对于
whater
的运行时类型的某个类型,将调用某个不带参数的方法
Blah()
,并且该类型等于或派生自声明
Blah()的类型
。(事实上,您知道的更多:您知道它等于编译时类型的
或从编译时类型派生而来的任何东西)
)虚拟绑定是动态绑定的一种形式,但它不是完全动态的。用户无法决定此调用是否应指向不同类型层次结构上的不同方法


反射使我们能够在运行时完全基于用户选择(如果愿意)进行绑定的调用。我们付出了性能损失,我们失去了编译时类型安全性,但我们获得了在运行时100%决定调用什么代码的灵活性。在某些情况下,这是一个合理的折衷。

反射是.NET框架中非常深入的一部分,以至于您常常不知道自己正在这样做(例如,请参见属性和LINQ)。当你知道自己在做的时候,即使感觉不对,这可能是实现特定目标的唯一途径

除了Eric在这里提到的两大领域之外,还有一些其他领域。还有很多,这些只是我马上想到的一些

序列化(和类似) 无论您是使用XML还是JSON,还是使用自己的,当您不必为每个类编写特定的代码来启用序列化时,序列化对象都要容易得多。反射使您能够枚举对象中已标记(或未标记)序列化的属性,并将它们写入输出

但这并不是关于拯救国家。反射允许我们编写可以产生业务输出的通用方法,比如来自任意集合的CSV或XLSX文件。我从
ToCSV(…)
ToExcel(…)
扩展中获得了很多好处,比如在基于web的报告中生成数据集的可下载版本

访问隐藏数据 是的,我知道,这是个骗局。是的,埃里克可能会为此打我一巴掌,但是

有很多代码——我在看你,ASP.NET——隐藏在
private
protected
后面的有趣和有用的东西。有时候,唯一的办法就是使用反射。有时这不是唯一的方法,但也可以是更简单的方法

属性 每次将
属性
标记到一个类、方法等上时,都会隐式提供将通过反射访问的数据。想自己使用这些属性吗?反思是你获得它们的唯一途径

LINQ和其他表达式 这些天这真的很重要。如果您曾经使用过LINQtoSQL、实体框架等,那么您在某种程度上使用过
Expression
。您可以编写一个简单的小POCO来表示数据库表中的一行,其他一切都由反射处理。编写谓词表达式时,系统使用反射模型构建结构,然后对这些结构进行处理(访问)以构建SQL语句

表达式也不仅仅适用于LINQ,一旦你知道自己在做什么,你就可以自己做一些真正有趣的事情。我有代码为CSV导入生成行解析器,当编译到
Func
时,这些行解析器运行得非常快。现在我倾向于使用别人编写的映射器,但当时我需要将一个定期上传到网站的20K记录文件的总导入时间再减少几%

P/调用编组 这一次在幕后是一件大事,偶尔在前台也是如此。当您想要调用Windows API函数或使用本机DLL时,P/Invoke为您提供了实现这一点的方法,而无需在两个方向上构建内存缓冲区。编组方法使用反射来翻译某些东西——字符串等就是明显的例子——这样你就不必操心了。所有都是基于<代码>类型< /代码>对象,它是反射的基础。< /P>
事实是,毫无疑问