现实世界使用Reflection.Emit

问题描述 投票:37回答:17

在我读过的所有书中,他们经常说,你想要动态生成IL的情况并不多,但他们没有给出任何有意义的例子。

在看到Reflection.Emit作为游戏公司的工作要求后,我很好奇其他地方正在使用它。

我现在想知道在现实世界中是否有任何情况,这是解决问题的最佳方法。也许它被用作设计模式的实现?

注意我想象PostSharp / AOP使用它。

c# .net reflection reflection.emit
17个回答
13
投票

Expression.Compile基本上是这样做的 - 这是一些LINQ的关键。

我目前正在使用反射发射来重新编写序列化API - 因为有时反射不够好。碰巧这也会让它产生dll(就像sgen的工作原理一样),允许完全静态的代码(我希望这会让iPhone变得友好)。

我还在HyperDescriptor中使用类似的方法来提供非常快速的基于名称的属性查找。

我也使用emit做以下事情:

所有都与SO问题有关。

最后,这种IL方法是protobuf-net“v2”的核心;这里的原因是它允许我在运行时拥有一个快速模型(通过IL动态编译它),并将其直接写入静态编译的dll,以便它适用于iPhone,Phone 7之类的东西等(缺少必要的元编程API)。


2
投票

我最近用它创建了一个概念验证,用于编译一组在运行时非常昂贵的操作,并且速度提高了200%。操作是使用RegEx来解析一个大字符串,并循环匹配,使用Reflection来查找和实例化类型,以及一些其他不完全快的东西。通过使用IL emit,我创建了与委托类型(使用DynamicMethod)匹配并缓存它们的动态函数。我按照每个输入值做了一次正常的RegEx / Reflection舞蹈,以确定它应该做什么,然后使用StringBuilder将字符串连接为文字,而不是Reflection / Activator我现在可以在发出的IL中使用实际类型本身。这是一个有用的提示:不要试图自己写IL,除非你是一个sado-masochist。编写一个示例函数或键入C#,它可以执行您想要的操作,编译它,并使用Reflector或ILDASM查看生成的IL。然后使用Emit做类似的逻辑。另一个提示是你可以创建本地并将它们存储到变量中,然后使用Emit(OpCodes.Ldloc,myLocalVar)它将为你获取本地地址,而不必跟踪本地索引(即ldloc_1)。


1
投票

1
投票
  1. 生成声明性代码,例如使用接口声明底层HTTP REST服务。 https://github.com/neurospeech/retro-core-fit
  2. 性能提升,大多数时候我使用Expression.Compile来创建代码片段,通过编译给已编译委托的表达式来快速检索信息,这可以在将来执行。如果使用PropertyInfo.GetValue,它会非常慢,但如果您创建一个表达式来访问属性并将其编译为委托(内部使用Reflection.Emit),则可以节省大量CPU时间。

0
投票

Reflection.Emit命名空间用于开发LinqPad。它有助于动态创建类型化的Datacontexts。看看这个链接http://www.linqpad.net/HowLINQPadWorks.aspx


0
投票

我喜欢探索更多AI-Inspired用于自学。它允许我们在运行时创建类或模块


0
投票

例如,Entity Framework使用Reflection.Emit在运行时构建代理类,它继承自模型类以提供延迟加载和更改跟踪。


0
投票

从外部数据生成枚举:

Dynamic enum in C#

在该示例中,数据来自查找数据库,并且通过读出数据库在编译时创建枚举。这样可以保持类型安全,而无需手动维护重复的信息源。


0
投票

我实际上正在开发自己的语言,我正在使用.NET Framework的Reflection.Emit构建其编译器。 有人可能会认为使用C#构建编译器并不好,但实际上工作正常并且编译时性能足够好。此外,这显然与运行时性能无关,这将取决于CLR,而不是我的编译器(除了像运算符优先级这样的最小优化)。一旦我完成它,我就会在GitHub上发布它。


10
投票

动态生成实现某种接口的mock object。执行此操作的示例框架:moqrhino mocks


8
投票

我正在使用它作为一种动态创建动态代理来包装类的方法。 NHibernate使用相同的模式来代理对POCO对象的调用,而不是查询数据库。

任何时候你想要能够动态地“编写代码”(即创建一个新的函数等),你需要Emit


7
投票

Castle DynamicProxy将它用于动态代理。然后,Castle的IoC容器Windsor和OR映射器ActiveRecord使用DynamicProxy。


6
投票

DLR和DLR相关语言严重依赖Reflection.Emit


4
投票

我记得在第8章中使用Relection.EmitBeautiful Code的“图像处理的动态代码生成”。基本上,作者专门用于对给定图像执行某组图像处理操作的功能,这反过来导致执行时间大大减少。


3
投票

我在一个应用程序中使用它,其中必须通过反射重复访问属性(因为在编译时不知道属性名称)。

通过在运行时创建一个生成用于访问属性的代码的辅助类,生成的代码比原始的仅反射代码快一个数量级。


2
投票

XMLSerializer实际上生成代码并在首次运行时编译它。如果您知道这种情况正在发生,您可以阅读有关如何调试XML序列化的this great blog post on Scott Hanselman's site


2
投票

模拟库也使用Reflection.Emit生成单元测试中使用的代理。

© www.soinside.com 2019 - 2024. All rights reserved.