问题标签 [reflection.emit]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
1931 浏览

c# - 在 C#/.NET 4.0 中填充和使用动态类

在我们的应用程序中,我们正在考虑使用动态生成的类来保存我们的大量数据。这样做的原因是我们的客户的表具有不同的结构。因此,您可以有一个名为“DOG”的客户表(只是编造这个),其中包含“DOGID”、“DOGNAME”、“DOGTYPE”等列。客户 #2 可以具有与“列”相同的表“DOG” DOGID”、“DOG_FIRST_NAME”、“DOG_LAST_NAME”、“DOG_BREED”等。我们不能在编译时为这些创建类,因为客户可以随时更改表模式。

目前我的代码可以在运行时使用反射生成一个“DOG”类。我想弄清楚的是如何从 DataTable(或其他一些 .NET 机制)中填充此类,而不会造成极大的性能损失。我们有一张包含约 20 列和约 50k 行的表。对所有行和列执行 foreach 以创建集合大约需要 1 分钟,这有点太长了。

我是想提出一个过于复杂的解决方案,还是我走在正确的轨道上?有没有其他人遇到过这样的问题?创建动态类是微软开发人员提出的解决方案。如果我们可以填充这个集合并有效地使用它,我认为它可以工作。

0 投票
3 回答
3027 浏览

c++ - 周围有运行时 C++ 汇编程序库吗?

对于我的小型爱好项目,我需要在运行时从 C++ 程序发出机器代码。我有基地址 0xDEADBEEF 并想写这样的东西:

内联汇编器不是我的选择,因为生成的机器代码取决于程序状态。

有人知道这样做的现有图书馆吗?如果不是,从头开始开发并使其开源是个好主意吗?(我的意思是,如果这个库存在的话,有人会使用它吗?)

0 投票
1 回答
915 浏览

c# - 在同一类型的 ILGenerator 上调用动态生成的方法

通常,当我想在另一个正在编写相同类型的方法的 ILGenerator 对象中调用动态方法时,我会执行以下操作:

但是,我遇到了以下问题:我无法引用我要调用的方法的方法构建器,因为它是由另一个框架生成的(我只获得了对当前 TypeBuilder 的引用)。此方法在当前动态类型的基类中被定义为受保护的虚拟(并且在我无法获得引用的方法构建器上被覆盖),我可以通过这样做来获得对它的引用:

问题是这调用了基类型的方法,而不是覆盖的方法。

有什么方法可以让我引用一个只有对定义它的类型构建器的引用的方法构建器?或者有没有一种方法可以使用 ILGenerator 调用方法而无需将“MethodInfo”对象传递给它?

0 投票
1 回答
866 浏览

silverlight - Silverlight 中的 System.CodeDom.Compiler.CompilerParameters 在哪里?

我想在 Silverlight 中创建数学表达式评估器。为了轻松做到这一点,我需要使用 System.Reflection、System.Reflection.Emit、System.CodeDom.Compiler 和其他相关程序集进行动态编译。

但是,我在 Silverlight 中找不到此类。

请给我一些建议。

0 投票
6 回答
6523 浏览

c# - 替换方法的 MethodBody 中的指令

(首先,这是一篇很长的帖子,但别担心:我已经实现了所有这些,我只是在问你的意见,或者可能的替代方案。)

我在执行以下操作时遇到了麻烦;我很感激一些帮助:

  1. 我得到一个Typeas 参数。
  2. 我使用反射定义了一个子类。请注意,我不打算修改原始类型,而是创建一个新类型。
  3. 我为原始类的每个字段创建一个属性,如下所示:

    /li>
  4. 对于超类的每个方法,我都会在子类中创建一个类似的方法。方法的主体必须相同,只是我将指令替换为ldfld xcallvirt this.get_X也就是说,我调用 get 访问器,而不是直接从字段中读取。

我在第 4 步遇到问题。我知道您不应该像这样操作代码,但我真的需要这样做。

这是我尝试过的:

尝试 #1:使用 Mono.Cecil。这将允许我将方法的主体解析为人类可读的Instructions,并轻松替换指令。但是,原始类型不在 .dll 文件中,所以我找不到使用 Mono.Cecil 加载它的方法。将类型写入 .dll,然后加载它,然后修改它并将新类型写入磁盘(我认为这是使用 Mono.Cecil 创建类型的方式),然后加载它似乎是一个巨大的开销。

尝试#2:使用 Mono.Reflection。这也将允许我将正文解析为Instructions,但我不支持替换指令。我使用 Mono.Reflection 实现了一个非常丑陋且效率低下的解决方案,但它还不支持包含 try-catch 语句的方法(尽管我想我可以实现这个)并且我担心可能存在其他场景它不起作用,因为我ILGenerator以一种不寻常的方式使用它。此外,它非常难看;)。这是我所做的:

这是可怕的,可怕的Reemit方法:

分支指令是一种特殊情况,因为instr.Operandis SByte,但Emit需要类型为 的操作数Label。因此需要Dictionary labels.

如您所见,这非常可怕。更重要的是,它并非在所有情况下都有效,例如包含 try- catch语句的方法BeginExceptionBlock,因为我没有使用. 这变得越来越复杂。我想我可以做到:有一个列表应该包含执行此操作的必要信息。但无论如何我都不喜欢这个解决方案,所以我会把它保存为最后的解决方案。BeginCatchBlockILGeneratorMethodBodyExceptionHandlingClause

尝试#3:直接复制返回的字节数组MethodBody.GetILAsByteArray(),因为我只想将一条指令替换为另一条相同大小的单条指令,该指令产生完全相同的结果:它在堆栈等。所以不会有任何标签移动,一切都应该完全一样。我已经这样做了,替换了数组的特定字节,然后调用MethodBuilder.CreateMethodBody(byte[], int),但我仍然得到同样的异常错误,我仍然需要声明局部变量,否则我会得到一个错误......即使我只是复制方法的主体,不要改变任何东西。所以这更有效,但我仍然需要处理异常等。

叹。

这是尝试#3的实现,以防有人感兴趣:

(我知道它不漂亮。对不起。我很快把它放在一起看看它是否有用。)

我不抱太大希望,但有人能提出比这更好的建议吗?

很抱歉这篇文章太长了,谢谢。


更新#1: Aggh ...我刚刚在msdn文档中阅读了这个:

[CreateMethodBody 方法] 目前不完全支持。用户无法提供令牌修复和异常处理程序的位置。

在尝试任何事情之前,我真的应该阅读文档。总有一天我会学...

这意味着选项 #3 不支持 try-catch 语句,这对我来说毫无用处。我真的必须使用可怕的#2吗?:/ 帮助!:P


更新#2:我已经成功实现了尝试#2,支持异常。这很丑陋,但它有效。当我稍微改进代码时,我会在这里发布。这不是优先事项,因此可能需要几周后。只是让你知道,以防有人对此感兴趣。

感谢您的建议。

0 投票
0 回答
390 浏览

.net - 与其他程序集生成技术相比,Reflection.Emit 有哪些限制?

我过去曾使用 Reflection.Emit 来编写编译器,但我知道标准编译器不使用它,并且在这里对另一个问题的回答中,我看到提到有些东西 Reflection.Emit 无法做到做。

如果我打算为 .NET 编写另一个编译器,我应该注意的 Reflection.Emit 有哪些限制?

0 投票
1 回答
628 浏览

c# - 动态代码生成问题

这段代码 gif 异常:调用异常,请帮忙,我不知道发生了什么,我认为是 Add 的问题,因为当我推入堆栈整数时他工作,当我推左值时它没有工作,谢谢

0 投票
3 回答
1444 浏览

.net - .NET 中类型名称的最大长度是多少

可能重复:
C#/CLI 标识符的最大长度是多少?

生成动态程序集和类型时,类型名称的长度限制是什么?

0 投票
1 回答
688 浏览

c# - IL 短格式指令不短?

我正在使用 Reflector 查看有效方法的 IL 代码,我遇到了这个问题:

带有后缀.s的指令应该采用 int8 操作数,果然这也应该是 Leave_S 的情况。但是0x0103是259,超出了一个int8的容量。该方法以某种方式起作用,但是当我使用Mono.Reflection.Disassembler.GetInstructions它检索的方法阅读说明时

也就是说,3 而不是 259,因为它应该是 int8。所以,我的问题是:原始指令 ( leave.s L_0103) 怎么可能?我已经查看了ECMA 文档(第III 部分:CIL 指令集),但找不到任何解释它的内容。

有任何想法吗?谢谢。


编辑#1:好的,我是个白痴。在分支指令的情况下,偏移量必须从当前指令之后的指令的开头开始计算。我发誓我阅读了文档,但不知何故我设法跳过了它。在我的辩护中,我今天病得很重。叹。

谢谢你。(感谢你没有叫我白痴,尽管这很白痴:P)


编辑#2:顺便说一句,如果有人感兴趣,当Mono.Reflection.Disassembler.GetInstructions反汇编指令时,它会改变分支指令中操作数的含义。特别是,正如已经指出的那样,分支指令的操作数表示从下一条指令开始的偏移量,而不是从 0 开始的偏移量。但是,Mono.Reflection返回从 0 开始的偏移量(这可能是我感到困惑的原因;虽然它没有解释我是如何设法跳过部分文档的)。

的提取物MethodBodyReader.ReadOperand(Instruction instruction)

如您所见,它添加了il.position,这是下一条指令的偏移量(从 0 开始)。此外,它转换为sbyte,这就是我得到 3 而不是 259 的原因。这似乎是一个错误(从 0 开始的偏移量可能大于 a sbyte)。我会问 Jb Evain(作者)并报告。


编辑#3:他还没有回答,但我已将其更改为:

它似乎解决了我的问题。如果它是向后跳跃(负偏移),我会转换sbyte为正确的符号,然后当我添加il.position(这是一个int)时,结果是一个int

无论如何,我会让你知道他说什么。


编辑#4:我忘了报告。作者确认这是一个错误。

0 投票
2 回答
1561 浏览

c# - 使用 System.Reflection.Emit 在枚举字段上创建 DescriptionAttribute

我有一个字符串列表,这些字符串是枚举值的候选者。他们是

  • 不要发送差异
  • 500行
  • 1000 行
  • 5000 行
  • 发送整个差异

问题是空格、特殊字符不是标识符的一部分,甚至不能以数字开头,所以我会将这些值清理为仅字符、数字和 _

为了保留原始值,我想将这些字符串放在 DescriptionAttribute 中,这样最终的值Enum应该像

然后稍后使用代码我将检索与枚举值关联的真实字符串,以便可以将正确的字符串发送回 Web 服务以获取正确的资源。

我想知道如何创建DescriptionAttribute使用 System.Reflection.Emit

基本上问题是在哪里以及如何存储原始字符串,以便在选择 Enumeration 值时,可以检索相应的值。

我也有兴趣知道如何DescriptionAttribute 在需要时访问。