【问题标题】:Real world uses of Reflection.EmitReflection.Emit 的真实使用
【发布时间】:2011-01-19 17:39:45
【问题描述】:

在我读过的关于反思的所有书籍中,他们经常说您想要即时生成 IL 的情况并不多,但他们没有给出任何示例说明它在哪里有意义。

在看到 Reflection.Emit 是一家游戏公司的工作要求后,我很好奇它还有什么用处。

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

注意 我想PostSharp / AOP 使用它。

【问题讨论】:

  • PostSharp 执行后编译步骤,但不会在运行时发出代码。
  • 听起来是社区 wiki 的好人选。 :)
  • 我知道这有点晚了,但是 - 我们现在使用的网站 (stackoverflow.com) 正在大量使用 dapper,这使得(大量)使用 Reflection.Emit。
  • 我以为 Dapper 使用 CodeDOM 来生成模型类。

标签: c# .net reflection reflection.emit


【解决方案1】:

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

任何时候您希望能够动态地“编写代码”(即创建新函数等),您都需要Emit

【讨论】:

  • 在 System.Linq.Expressions 命名空间通过Compile() 方法发挥作用之前,这一点更为正确。
  • 我应该补充一点,当我将一些 Emit 代码切换为 Expressions 代码时,一些幻像错误会自行解决。它基本上适用于每个地方都更清洁,更易于维护。
  • 表达式编译方法有一个巨大的限制,只能在没有语句体的 lambda 上工作
【解决方案2】:

【讨论】:

  • 有趣.. 使用 Duck Typing 有什么意义?
  • 对于模拟,您可能需要使用 Process 作为底层实现的 IProcess 代理。
  • 链接已失效。
【解决方案3】:

XMLSerializer 实际上会生成代码并在第一次运行时对其进行编译。如果您知道发生这种情况,可以阅读this great blog post on Scott Hanselman's site 了解如何调试 XML 序列化。

【讨论】:

  • 帖子建议 XMLSerializer 实际上生成 C# 代码并编译它而不是直接发出 IL。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    Castle DynamicProxy 使用它,你猜,动态代理。然后城堡的 IoC 容器 Windsor 和 OR 映射器 ActiveRecord 使用 DynamicProxy。

    【讨论】:

    • ...和 ​​Rhino Mocks 和 Moq 和 NHibernate 以及整套其他框架和应用程序 ;)
    【解决方案6】:

    Mocking 库也使用 Reflection.Emit 来生成用于单元测试的代理。

    【讨论】:

      【解决方案7】:

      动态生成一个mock object,它实现了一些接口。执行此操作的示例框架:moqrhino mocks

      【讨论】:

        【解决方案8】:

        我记得在Beautiful Code 的第 8 章:“用于图像处理的动态代码生成”中看到了 Relection.Emit。基本上,作者专门设计了一个函数,用于对给定图像进行一组特定的图像处理操作,从而大大减少了执行时间。

        【讨论】:

          【解决方案9】:

          Expression.Compile 本质上就是这样做的——这是 一些 LINQ 的关键。

          我目前正在使用反射发射来重写序列化 API - 因为有时反射还不够好。碰巧这也将允许它生成 dll(很像 sgen 的工作方式),允许完全静态代码(我希望这将使它对 iPhone 友好)。

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

          我还使用了 emit 来执行以下操作:

          都与 SO 问题有关。

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

          【讨论】:

          • 能否提供您提到的问题的链接?
          【解决方案10】:

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

          【讨论】:

            【解决方案11】:

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

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

            【讨论】:

            • 我刚刚编写了一个库来执行此操作,但它使用 Expression 树而不是 Reflection.Emit
            【解决方案12】:

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

            【讨论】:

              【解决方案13】:

              我喜欢探索更多受 AI 启发的自我学习。它允许我们在运行时创建一个类或模块

              【讨论】:

                【解决方案14】:

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

                【讨论】:

                  【解决方案15】:

                  从外部数据生成枚举:

                  Dynamic enum in C#

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

                  【讨论】:

                    【解决方案16】:
                    1. 生成声明性代码,例如使用接口声明底层HTTP REST服务。 https://github.com/neurospeech/retro-core-fit

                    2. 性能助推器,大多数时候我使用Expression.Compile 创建一个代码片段,通过编译给已编译委托的表达式来快速检索信息,该委托可以在将来执行。如果你使用PropertyInfo.GetValue,它会很慢,但是如果你创建一个表达式来访问属性并将其编译为一个委托(它在内部使用Reflection.Emit),它会大大节省CPU时间。

                      李>

                    【讨论】:

                      【解决方案17】:

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

                      【讨论】:

                        猜你喜欢
                        • 2011-04-08
                        • 1970-01-01
                        • 2023-03-26
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多