在我阅读的所有书籍中,他们经常说,你想要动态生成IL的情况并不多,但他们并没有提供任何有意义的例子。
在看到Reflection.Emit作为游戏公司的工作要求之后,我很好奇它在哪里被使用。
我现在想知道在现实世界中是否有任何情况,这是解决问题的最佳方法。也许它被用作设计模式的实现?
注意 我想PostSharp / AOP使用它。
答案 0 :(得分:13)
Expression.Compile
基本上是这样做的 - 这是 LINQ的一些的关键。
我目前正在使用反射发射来重新编写序列化API - 因为有时反射不够好。碰巧这也会让它产生dll(就像sgen的工作原理一样),允许完全静态的代码(我希望这会让iPhone变得友好)。
我还在HyperDescriptor中使用类似的方法来提供非常快速的基于名称的属性查找。
我也使用emit来做类似的事情:
所有与SO问题相关。
最后,这种IL方法是protobuf-net“v2”的核心;这里的原因是它允许我两个在运行时拥有一个快速模型(通过IL动态编译它),和将它直接写入静态 - 编译dll,以便它适用于iPhone,Phone 7等(缺少必要的元编程API)。
答案 1 :(得分:10)
动态生成实现某个接口的mock object。执行此操作的示例框架:moq,rhino mocks。
答案 2 :(得分:8)
我正在使用它作为一种动态创建动态代理以包装类的方法。 NHibernate使用相同的模式来代理对POCO对象的调用,而不是查询数据库。
如果您希望能够动态“编写代码”(即创建新功能等),则需要Emit
。
答案 3 :(得分:7)
Castle DynamicProxy会将其用于动态代理。然后,Castle的IoC容器Windsor和OR映射器ActiveRecord使用DynamicProxy。
答案 4 :(得分:6)
DLR和DLR相关语言严重依赖Reflection.Emit
答案 5 :(得分:4)
我记得Relection.Emit
在第8章中使用了{{1}}:Beautiful Code的“图像处理的动态代码生成”。基本上,作者专门用于在给定图像上执行某组图像处理操作的功能,这反过来会大大缩短执行时间。
答案 6 :(得分:3)
我在一个必须通过反射重复访问属性的应用程序中使用它(因为在编译时不知道属性名称)。
通过在运行时创建一个生成用于访问属性的代码的辅助类,生成的代码比原始的仅反射代码快一个数量级。
答案 7 :(得分:2)
XMLSerializer实际上生成代码并在首次运行时编译它。如果您知道这种情况正在发生,您可以阅读有关如何调试XML序列化的this great blog post on Scott Hanselman's site。
答案 8 :(得分:2)
模拟库也使用Reflection.Emit生成单元测试中使用的代理。
答案 9 :(得分: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)。 / p>
答案 10 :(得分:1)
答案 11 :(得分:1)
生成声明性代码,例如使用接口声明基础HTTP REST服务。 https://github.com/neurospeech/retro-core-fit
性能增强器,大多数时候,我使用Expression.Compile
来创建一段代码,以通过将表达式提供给已编译的委托人来快速检索信息,该表达式可以在将来执行。如果使用PropertyInfo.GetValue
,速度会很慢,但是如果创建一个表达式来访问属性并将其编译为委托(内部使用Reflection.Emit),则可以节省大量的CPU时间。
答案 12 :(得分:0)
我喜欢探索AI-Inspired for self-learning的更多内容。它允许我们在运行时创建一个类或模块
答案 13 :(得分:0)
例如实体框架使用Reflection.Emit
在运行时构建代理类,该代理类从模型类继承以提供延迟加载和更改跟踪
答案 14 :(得分:0)
答案 15 :(得分:0)
Reflection.Emit命名空间用于开发LinqPad。它有助于动态创建类型化的Datacontexts。查看此链接http://www.linqpad.net/HowLINQPadWorks.aspx。
答案 16 :(得分:0)
我实际上是在开发自己的语言,并且正在使用C#的Reflection.Emit
构建其编译器。
有人可能会认为使用C#构建编译器不好,但是实际上一切正常,并且编译时性能也足够好。
完成后,我会在GitHub上发布它。