反映用例

时间:2020-03-05 18:49:22  来源:igfitidea点击:

最近,我正在与一位有关C ++的同事交谈,并感叹说无法用类字段的名称来提取字符串并提取具有该名称的字段。换句话说,它缺乏反思。他给我茫然的表情,问什么时候有人需要做这样的事情。

除了"嘿,我现在需要这样做"以外,我没有为他提供任何好答案。所以我坐下来,想出了我用各种语言进行反射时实际完成的一些工作的清单。不幸的是,我的大多数示例都来自我的Python网络编程,我希望这里的人们能有更多的示例。这是我想出的清单:

  • 给定一个带有x =" Hello World!"这样的行的配置文件y = 5.0动态地将某些" config"对象的字段设置为等于该文件中的值。 (这就是我希望可以在C ++中完成的工作,但实际上却做不到。)
  • 在对对象列表进行排序时,请根据配置文件或者Web请求中给定属性名称的任意属性进行排序。
  • 在编写使用网络协议的软件时,反射使我们可以基于该协议中的字符串值来调用方法。例如,我写了一个IRC机器人,它将"!some_command arg1 arg2"转换为一个名为" actions.some_command(arg1,arg2)"的方法,并打印出返回该函数的所有内容。
  • 当使用Python的__getattr__函数(类似于Ruby / Smalltalk中的method_missing)时,我正在使用具有大量统计信息的类,例如late_total。对于每个统计信息,我都希望能够添加_percent以使该统计信息占我所计算的总数的百分比(例如stats.late_total_percent)。反思使这一过程变得非常容易。

那么,在反思的过程中,这里的任何人都可以根据自己的编程经验提供任何示例吗?下次同事问我为什么我"想做这样的事情"时,我想做更多的准备。

解决方案

回答

很多时候,我们想动态实例化并使用类型,直到运行时才知道类型的对象。例如,使用OR-映射器或者插件体系结构。如果要编写日志记录库,并且要动态检查异常的类型和属性,则模拟框架可以使用它。

如果再想一想,我可能会想出更多的例子。

回答

编写调度程序。 Twisted使用python的反射功能来分派XML-RPC和SOAP调用。 RMI使用Java的反射API进行分派。

命令行解析。根据传入的命令行参数构建配置对象。

在编写单元测试时,使用反射可能会有所帮助,尽管大多数情况下,我使用它来绕过访问修饰符(Java)。

回答

当框架或者我要访问的第三方库中存在某些内部或者私有方法时,我在C中使用了反射。

(免责声明:这不一定是最佳实践,因为在以后的版本中可能会更改私有方法和内部方法。但是它可以满足我的需要。)

回答

好吧,在静态类型的语言中,我们需要在需要进行"动态"操作的任何时候使用反射。它可以方便地用于工具目的(扫描对象的成员)。在Java中,它在JMX和动态代理中使用了很多。在很多一次性案例中,这实际上是唯一的方法(几乎在任何时候我们需要执行编译器不允许我们执行的操作时)。

回答

我已经使用反射来获取有关异常,日志记录等的当前方法信息。

string src = MethodInfo.GetCurrentMethod().ToString();
string msg = "Big Mistake";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;

代替

string src = "MyMethod";
string msg = "Big MistakeA";
Exception newEx = new Exception(msg, ex);
newEx.Source = src;

复制/粘贴继承和代码生成更容易。

回答

我现在处于这样一种情况,我有大量的XML流通过线进入,我需要实例化一个Entity对象,该对象将从流中的元素中填充自身。使用反射来找出哪个Entity对象可以处理哪个XML元素比编写一条庞大的,维护噩梦的条件语句要容易得多。 XML模式与我如何构造和命名对象之间显然存在依赖关系,但是我可以同时控制两者,因此这不是一个大问题。

回答

我可以列出以下用法以进行反思:

  • 后期装订
  • 安全性(出于安全原因不完整的代码)
  • 代码分析
  • 动态打字(没有反射就无法进行鸭子打字)
  • 元编程

根据我的个人经验,在现实世界中使用了一些反射:

  • 开发基于反射的插件系统
  • 使用面向方面的编程模型
  • 执行静态代码分析
  • 使用了各种依赖注入框架
  • ...

反思是一件好事:)

回答

如果输入数据(如xml)具有复杂的结构且很容易映射到对象实例,或者我需要实例之间的某种"是"关系,则反射非常有用。

因为反射在Java中相对容易,所以有时我将其用于简单数据(键-值映射),其中我有一组固定的小键。一方面,很容易确定键是否有效(如果该类具有setter setKey(String data)),另一方面,我可以更改(文本)输入数据的类型并隐藏转换(例如,简单的强制转换) int in getKey()),因此应用程序的其余部分可以依赖正确键入的数据。
如果某个对象的某些键值对的类型发生了变化(例如,从int到float的形式),则只需要在数据对象及其用户中进行更改,而不必记住也要检查解析器。如果性能是一个问题,这可能不是明智的选择。

回答

我通常使用反射进行调试。反射可以比各种打印语句更轻松,更准确地显示系统中的对象。在具有一流功能的许多语言中,我们甚至可以调用对象的功能而无需编写特殊代码。

但是,有一种方法可以做我们想要的。使用哈希表。存储以字段名称为关键字的字段。

如果确实需要,则可以创建标准的"获取/设置"功能,也可以创建即时执行的宏。 #define GetX()Get(" X")`之类的东西。

我们甚至可以通过这种方式实现自己的不完美反射。

对于高级用户,如果可以编译代码,则可以启用调试输出生成并使用它来执行反射。