如果反思效率低下,何时最合适呢?

我发现很多案例,我认为我可以使用relfection来解决问题,但我通常不这样做,因为我听到了很多“不使用reflection,效率太低”的说法。

现在我处于一个我遇到问题的位置,我找不到任何其他解决方案而不是使用new T()reflection,如本问答中所述 。

所以我想知道是否有人可以告诉我反思的具体用途,以及是否有一套指导方针来表明它何时合适以及什么时候不合适?

它通常“足够快”,如果您需要更快(对于紧密循环等),您可以使用ExpressionILGenerator (可能通过DynamicMethod )进行元编程,以制作极其快速的代码(包括一些您无法做到的技巧) C#)。

reflection更常用于框架/库场景,其中库按定义对调用者一无所知,并且必须基于配置,属性或模式工作。

如果有一件事我讨厌听到它“不使用reflection,那就太低效了”。

什么效率太低? 如果您正在编写一个每月运行一次并且不是时间关键的控制台应用程序, 那么由于您使用reflection,它是否需要30秒而不是28秒才真正重要?

什么时候使用不合适的指南只有你真正可以组合在一起,因为它们严重依赖于你正在做的事情和效率/效率的替代方案。

代码效率的一个有用的抽象是将它分为三类时间,每个时间间隔大约3个数量级。

首先是人类时间。 当你只需要让一个人对代码的性能感到满意时,你可以做很多事情。 人类无法感知需要10毫秒或20毫秒的代码之间的差异,两者都是即时的。 当一个程序需要6秒而不是5秒时,人类就会宽容,大约需要30 亿个机器指令。 在人工时运行的程序的常见示例是编译器和点击设计器。 使用reflection绝不是问题。

然后有I / O时间。 当您的程序需要访问磁盘或网络时。 I / O很慢,在磁盘的情况下受到机械运动的限制,在网络的情况下是带宽和延迟。 您总是可以判断I / O何时成为瓶颈,您的程序正在运行,但它并没有大大增加CPU负载。 操作系统不断阻塞线程,使其等待I / O请求完成。

reflection在I / O时间运行。 要检索类型数据,CLR必须读取程序集元数据。 如果之前没有这样做,程序将导致页面错误,要求操作系统从磁盘读取数据。 接下来的是,粗略地说,reflection可以使I / O绑定代码的速度只有两倍。 通常更好,因为在第一次性能打击之后,元数据被缓存并且可以更快地检索。 因此,反思通常是可接受的权衡。 规范示例是序列化和dbase ORM。

然后是机器时间。 CPU核心的原始性能是惊人的。 属性getter可以在0到1/2 纳秒之间的某个位置执行。 这与PropertyInfo.GetValue()相比没有优势。 两者都会使CPU保持忙碌,你会看到核心的CPU负载为100%。 但GetValue()花费数百甚至数千个机器代码指令。 不计算在元数据中寻呼所需的时间。 虽然没有多少增量时间,但在循环时它会快速建立。

如果您无法在人工时间或I / O时间类别中对reflection代码进行分类,则reflection不太可能是常规代码的合适替代。

保持reflection不会减慢程序的关键是不要在循环中使用它。 如果要在启动期间从对象读取属性(发生一次),请使用reflection。 您希望从10,000个未知类型的对象列表中读取属性,使用reflection获取属性getter委托一次(搜索项: PropertyInfo.GetGetMethod ),然后调用委托10,000种类型。 StackOverflow上有很多这方面的例子。

反思效率不高。 它比直接呼叫效率低。 因此,当没有等效的编译时安全方法时,我会使用reflection。 恕我直言,reflection的问题不是效率,而是代码的脆弱性,因为它使用的魔法字符串非常重构不友好。

我将它用于插件体系结构 – 查看插件文件夹中的程序集,以查找标有自定义属性的方法,该属性指示有关插件的信息 – 以及在日志记录框架中。 框架检测程序集本身的自定义属性,该属性包含有关程序集作者,项目,版本信息以及与堆栈跟踪中的所有内容一起记录的其他标记的信息。

要放弃“商业秘密”,但这是一个好的。 框架允许您使用’Story ref’标记每个方法或类,例如

[StoryRef(Ref="ImportCSV1")]

…并且它的想法是它将集成到我们的敏捷项目管理框架中:如果在该类/方法中抛出任何exception,则日志记录方法将使用reflection来检查堆栈跟踪中的StoryRef属性,如果是,那么将被记录为该故事的例外。 在PM软件中,您可以看到Story的exception(一个故事就像一个极端/敏捷的用例)。

我认为这是一个有效的用途,至少! 基本上,当它看起来是最干净 ,最合适的方式时,我会使用reflection。 没有其他任何东西可以真正融入其中 – 我无法想象你会使用reflection来做出许多效率会产生效果的场合。

所以我想知道是否有人可以告诉我反思的具体用途,以及是否有一套指导方针来表明它何时合适以及什么时候不合适?

反思的一个例子来自维基百科 :

 //Without reflection Foo foo = new Foo(); foo.Hello(); //With reflection Type t = Type.GetType("FooNamespace.Foo"); object foo = Activator.CreateInstance(t); t.InvokeMember("Hello", BindingFlags.InvokeMethod, null, foo, null); 

在这里,使用reflection没有任何好处:使用非reflection代码不仅更有效,而且更容易理解。

reflection的良好用途是序列化和对象关系映射,如果你有一个类的属性列表,它们很容易实现,但是否则需要为每个类定制一个自定义函数。