所以,我最近做了一些实验,发现 Reflection.Emit 似乎并不支持 ECMA 规范中的所有操作码。缺少 3 个操作码:
ldelem.any
stelem.any
no.
(字首)
反射 API 是否不支持这些操作码,或者有什么方法可以生成它们?
所以,我最近做了一些实验,发现 Reflection.Emit 似乎并不支持 ECMA 规范中的所有操作码。缺少 3 个操作码:
ldelem.any
stelem.any
no.
(字首)反射 API 是否不支持这些操作码,或者有什么方法可以生成它们?
事实上,你可以。
在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
页面上的下拉菜单允许您选择可以在其中执行此操作的许多版本的框架。
我对此发表了评论,但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 上操作,它是通用方法参数。