在我读过的所有关于反思的书中,他们经常说没有多少情况需要即时生成 IL,但他们没有给出任何有意义的例子。
在看到 Reflection.Emit 是一家游戏公司的工作要求后,我很好奇它还有什么用处。
我现在想知道您在现实世界中是否见过任何情况,这是解决问题的最佳方法。也许它被用作设计模式的实现?
注意 我想PostSharp / AOP 使用它。
在我读过的所有关于反思的书中,他们经常说没有多少情况需要即时生成 IL,但他们没有给出任何有意义的例子。
在看到 Reflection.Emit 是一家游戏公司的工作要求后,我很好奇它还有什么用处。
我现在想知道您在现实世界中是否见过任何情况,这是解决问题的最佳方法。也许它被用作设计模式的实现?
注意 我想PostSharp / AOP 使用它。
Expression.Compile
本质上就是这样做的——这是一些LINQ 的关键。
我目前正在使用反射发射来重新编写序列化 API - 因为有时反射还不够好。碰巧这也将允许它生成 dll(很像 sgen 的工作方式),允许完全静态代码(我希望这将使它对 iPhone 友好)。
我还在HyperDescriptor中使用了类似的方法来提供非常快速的基于名称的属性查找。
我还使用 emit 来执行以下操作:
所有与SO问题有关。
最后,这种 IL 方法是 protobuf-net "v2" 的核心;这里的原因是它允许我在运行时拥有一个快速模型(通过 IL 即时编译它),并将其直接写入静态编译的 dll,以便它可以在 iPhone、Phone 7 等设备上运行等(缺少必要的元编程 API)。
动态生成实现某些接口的模拟对象。执行此操作的示例框架:moq,rhino mocks。
我使用它作为动态创建动态代理来包装类的一种方式。NHibernate 使用相同的模式来代理对 POCO 对象的调用,而不是查询数据库。
任何时候您希望能够动态地“编写代码”(即创建新函数等),您都需要Emit
.
Castle DynamicProxy使用它,你猜,动态代理。然后城堡的 IoC 容器 Windsor 和 OR 映射器 ActiveRecord 使用 DynamicProxy。
DLR 和 DLR 相关语言严重依赖Reflection.Emit
我在一个必须通过反射重复访问属性的应用程序中使用它(因为在编译时不知道属性名称)。
通过在运行时创建一个辅助类来生成访问属性的代码,生成的代码比原始的仅反射代码快一个数量级。
我记得在Beautiful CodeRelection.Emit
的第 8 章:“On-the-Fly Code Generation for Image Processing”中看到过。基本上,作者专门针对给定图像执行一组特定图像处理操作的功能,从而大大减少了执行时间。
我最近使用它创建了一个概念证明,用于编译一组在运行时执行起来非常昂贵的操作,并且速度提高了 200%。这些操作是使用 RegEx 解析一个大字符串,并循环匹配,使用反射来查找和实例化类型,以及其他一些不太快的事情。通过使用 IL emit,我创建了与委托类型匹配的动态函数(使用 DynamicMethod)并将它们缓存起来。我对每个输入值进行了一次正常的 RegEx/Reflection 舞蹈,以确定它应该做什么,然后使用 StringBuilder 将字符串连接为文字,而不是 Reflection/Activator,我现在可以在发出的 IL 中使用实际类型本身。这是一个有用的提示:除非您是受虐狂,否则不要尝试自己编写 IL。在 C# 中编写一个示例函数或类型来执行您想要的操作,编译它,然后使用 Reflector 或 ILDASM 来查看生成的 IL。然后用 Emit 做类似的逻辑。另一个技巧是您可以创建本地变量并将它们存储到变量中,然后使用 Emit(OpCodes.Ldloc, myLocalVar) 它会为您获取本地地址,而不必跟踪本地索引(即 ldloc_1)。
XMLSerializer 实际上会生成代码并在第一次运行时对其进行编译。如果您知道这种情况正在发生,您可以阅读Scott Hanselman 网站上关于如何调试 XML 序列化的这篇很棒的博客文章。
模拟库也使用 Reflection.Emit 来生成用于单元测试的代理。
生成声明性代码,例如使用接口声明底层 HTTP REST 服务。 https://github.com/neurospeech/retro-core-fit
性能助推器,大多数时候我Expression.Compile
用来创建代码片段以通过编译给已编译委托的表达式来快速检索信息,该委托可以在将来执行。如果你使用PropertyInfo.GetValue
,它会很慢,但是如果你创建一个表达式来访问属性并将它编译为一个委托(它在内部使用 Reflection.Emit),它可以极大地节省 CPU 时间。
Reflection.Emit 命名空间用于开发 LinqPad。它有助于动态创建类型化的 Datacontexts。查看此链接http://www.linqpad.net/HowLINQPadWorks.aspx。
例如, Entity Framework用于Reflection.Emit
在运行时构建代理类,这些代理类继承自您的模型类,以提供延迟加载和更改跟踪。
我实际上正在开发自己的语言,并且正在使用 .NET Framework 的Reflection.Emit
.
有人可能会认为使用 C# 构建编译器并不好,但实际上一切正常,编译时性能也足够好。此外,这显然与运行时性能完全无关,这将取决于 CLR,而不是我的编译器(除了像运算符优先级这样的最小优化)。完成后我会在 GitHub 上发布它。
我喜欢探索更多关于 AI-Inspired for self-learning 的信息。它允许我们在运行时创建一个类或模块