我在学习反思,我得到了一些,但我并没有得到所有与这个概念相关的东西。为什么我们需要反射?我们需要反思的东西是什么我们做不到的?
发布于 2018-05-08 02:23:38
反射支持的场景很多很多,但我主要将它们分组到两个桶中。
例如,考虑关于程序集的最基本的问题:程序集中有哪些类型?程序集是自描述的,反射是将该描述显示到其他代码的机制。
例如,假设您想要编写一个程序,其中包含一个程序集,并对该程序集中的各个类之间的关系进行图形显示,以帮助您理解该代码。有这样的工具。他们在。--有人写了那些工具,,它们不是用魔法出现的。反射是设计在.NET框架中的一种机制,它允许您、我或任何人编写理解代码的工具。
假设您有一个静态方法Foo.Bar()。当您在程序中调用Foo.Bar()时,您可以100%肯定地知道,您认为将要调用的方法实际上将被调用。我们将静态方法称为“静态”,因为从name Bar到被调用的代码的绑定可以静态地理解--也就是说,无需运行程序。
现在考虑基类上的虚拟方法Blah()。当您调用whatever.Blah()时,您不知道编译时将确切地调用哪个Blah(),但是您知道,对于某个类型(即whatever的运行时类型),将调用一些没有参数的方法Blah(),并且该类型等于或派生于声明Blah()的类型。(实际上,您了解的更多:您知道它等于或派生于whatever的编译时类型。)虚拟绑定是动态绑定的一种形式,但并不是完全动态的。用户无法决定此调用应该是对不同类型层次结构上的不同方法的调用。
反射使我们能够进行完全在运行时绑定的调用,如果我们愿意的话,完全基于用户的选择。我们付出了性能上的代价,我们失去了编译时类型的安全性,但是我们获得了在运行时100%决定我们调用什么代码的灵活性。在某些情况下,这是一种合理的权衡。
发布于 2018-05-08 04:59:12
反射是.NET框架的一个很深的部分,因此您常常不知道自己在做什么(例如,请参阅属性和LINQ )。当你知道你在做这件事的时候,即使它感觉不对,它也可能是实现一个特定目标的唯一方法。
除了Eric在这里提到的两大领域之外,还有其他几个方面。还有更多,这些只是一些立即出现在脑海中。
序列化(及类似)
无论是使用XML、JSON还是滚动自己的对象,当您不必为每个类编写特定的代码以启用序列化时,序列化对象就容易得多。反射使您能够枚举对象中已标记为(或未标记为针对)的属性,并将它们写入输出。
但这与拯救州无关。反射允许我们编写能够产生业务输出的通用方法,比如从任意集合生成CSV或XLSX文件。我从ToCSV(...)和ToExcel(...)扩展中获得了很多经验,比如在基于web的报告中生成可下载的数据集。
访问隐藏数据
是的,我知道,这是个诡计的问题。是的,埃里克可能会因为这件事打我耳光,但是.
有很多代码--我正看着你,ASP.NET --隐藏了private或protected背后有趣而有用的东西。有时,唯一的办法是让他们出来是使用反射。有时这不是唯一的方法,但它可以是更简单的方式。
属性
每次将Attribute标记到类、方法等上时,都会隐式地提供要通过反射访问的数据。你想自己使用这些属性吗?反射是你获得它们的唯一途径。
LINQ和其他表达式
这些天这真的是很重要的事情。如果您曾经使用过LINQ、实体框架等,那么您就在某种程度上使用了Expression。您可以编写一个简单的小POCO来表示数据库表中的一行,其他一切都由反射来处理。编写谓词表达式时,系统将使用反射模型构建结构,然后处理(访问)这些结构以生成SQL语句。
表达式也不仅仅适用于LINQ,一旦你知道自己在做什么,你自己也会做一些非常有趣的事情。我有代码可以为CSV导入生成行解析器,这些代码在编译到Func<string, TRecord>时运行得非常快。这些天,我倾向于使用其他人写过的映射器,但当时我需要将一个包含20K记录并定期上传到网站的文件的总导入时间减少几%。
P/调用编组
这个在幕后很重要,偶尔也会出现在前台。当您想要调用Windows函数或使用本机DLL时,P/Invoke为您提供了实现这一目标的方法,而不必在两个方向构建内存缓冲区。编组方法使用反射来完成某些事情的转换--字符串等就是明显的例子--这样您就不必把手弄脏了。所有这些都基于Type对象,这是反射的基础。
事实是,如果没有反思,.NET框架就不会是现在的样子了。没有Attribute,没有Expression,语言之间的互操作可能要少得多。没有自动编组。没有LINQ。至少我们现在经常用它。
https://stackoverflow.com/questions/50224794
复制相似问题