是否可以使用Reflection.Emit作为操作码stelem.any和ldelem.any?

时间:2012-11-21 16:23:51

标签: .net reflection reflection.emit il dynamicmethod

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

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

这些操作码是否在Reflection API中不受支持,或者是否有某种方法可以生成它们?

2 个答案:

答案 0 :(得分: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

页面上的下拉菜单允许您选择框架的许多版本。

答案 1 :(得分:0)

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

请参阅使用情况,您必须对存储在数组中的类型进行编码,对于基元,有各种stelem.*操作码。如果您正在存储引用类型(声明为委托或类的东西),您将使用stelem.Ref并且您将Stelem (myType)用于值类型(被声明为结构或枚举的东西)

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

阵列的类型也可能是通用的,这会让事情变得相当困难。但更重要的是,它的逆向操作也有助于验证下一步操作。

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

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