【问题标题】:Is it possible to use Reflection.Emit for the opcodes stelem.any and ldelem.any?是否可以将 Reflection.Emit 用于操作码 stelem.any 和 ldelem.any?
【发布时间】:2012-11-21 16:23:51
【问题描述】:

所以,我最近做了一些实验,发现 Reflection.Emit 似乎并不支持 ECMA 规范中的所有操作码。缺少 3 个操作码:

  • ldelem.any
  • stelem.any
  • no.(前缀)

Reflection API 不支持这些操作码,还是有什么方法可以生成它们?

【问题讨论】:

  • 我很确定它是。让我检查一下;p
  • @leppie 那些操作码不在 OpCodes 集合中
  • Unbox_Any 在那里 ;p 编辑:至少在 v4 中
  • 顺便说一句,用 DynamicMethod 创建一个开放的泛型方法是不可能的。
  • @RenéWolferink 这是不可能的。它是一个结构,它的所有(可修改)成员都是内部的。我尝试使用反射将我自己的值注入其中,但我永远无法让它真正按预期运行

标签: .net reflection reflection.emit il dynamicmethod


【解决方案1】:

其实可以的。

http://msdn.microsoft.com/en-us/library/4xxf1410.aspx 有精彩的演练

两个基本部分是:

创建泛型参数:

string[] typeParamNames = {"TFirst", "TSecond"};
GenericTypeParameterBuilder[] typeParams = 
    myType.DefineGenericParameters(typeParamNames);

GenericTypeParameterBuilder TFirst = typeParams[0];
GenericTypeParameterBuilder TSecond = typeParams[1];

然后创建方法:

Type listOf = typeof(List<>);
Type listOfTFirst = listOf.MakeGenericType(TFirst);
Type[] mParamTypes = {TFirst.MakeArrayType()};

MethodBuilder exMethod = 
    myType.DefineMethod("ExampleMethod", 
        MethodAttributes.Public | MethodAttributes.Static, 
        listOfTFirst, 
        mParamTypes);

但是,您应该完全了解它,因为泛型参数以多种不同的方式和部分使用(在方法上、在参数上、作为结果类型、在调用时......)。

-update- 如果您想要 .NET 2 特定版本:http://msdn.microsoft.com/en-us/library/4xxf1410%28v=vs.80%29.aspx

页面上的下拉菜单可让您选择可以执行此操作的多个框架版本。

【讨论】:

  • @IllidanS4 我在编辑之前回答了这个问题。它可能不能完全回答现在的问题,但希望它对某些人仍然有用,所以我不想删除它。鉴于我在 3 年多前回答过这个问题,我不知道当时我的想法是什么。
【解决方案2】:

我对此发表了评论,但 OpCode.Stelem 指令至少在 .net 4 中转换为 stelem.any

过去的情况是,您必须对存储在数组中的类型进行编码,对于原语,有各种 stelem.* 操作码。如果您要存储引用类型(声明为委托或类的东西),您将使用 stelem.Ref 并将 Stelem (myType) 用于值类型(声明为结构或枚举的东西)。

然而,随着泛型的出现,类型参数出现了,它可以是它想要的任何东西。 T 可以是引用类型,也可以是值类型。所以stelem.any 就是为处理这种不寻常的情况而生的。但是你可能会说,我只能将一个未装箱的 T 存储到一个 T 数组中,所以它完全没有意义,我们不能只依赖数组的类型吗?

好吧,数组的类型也可能是泛型的,这会使事情变得相当困难。但更重要的是它的逆运算也有助于验证下一个运算。

ldarg.0
ldc.i4.0
ldelem.any !!T

告诉验证者这个堆栈转换之后的下一条指令应该在一个未装箱的 T 上操作,它是通用方法参数。

【讨论】:

  • 这些都不能告诉我你是否可以使用反射.emit 来做到这一点,你解释了为什么要添加 ldelem.any,但没有解释如何使用反射.emit 来做到这一点。
猜你喜欢
  • 1970-01-01
  • 2016-03-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2012-02-01
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
相关资源
最近更新 更多