我在生成的代理中使用以下代码进行版本跟踪:
ConstructorBuilder defaultConstructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);//typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
var defaultConstructorIL = defaultConstructor.GetILGenerator();
defaultConstructorIL.Emit(OpCodes.Ldarg_0);
defaultConstructorIL.Emit(OpCodes.Call, type.GetConstructor(Type.EmptyTypes));
defaultConstructorIL.Emit(OpCodes.Ldarg_0);
defaultConstructorIL.Emit(OpCodes.Ldc_I4, 0);
defaultConstructorIL.Emit(OpCodes.Stfld, version);
defaultConstructorIL.Emit(OpCodes.Ldarg_0);
defaultConstructorIL.Emit(OpCodes.Call, typeof(DateTime).GetProperty("UtcNow", BindingFlags.Public | BindingFlags.Static).GetGetMethod());
defaultConstructorIL.Emit(OpCodes.Stfld, lastUpdate);
defaultConstructorIL.Emit(OpCodes.Ret);
version是一个类型为“int”的FieldBuilder。在此配置中,我可以创建代理类型的实例,代理通过我的所有单元测试。
如果我将版本更改为Int64类型的字段,并将IL修改为:
defaultConstructorIL.Emit(OpCodes.Ldarg_0);
defaultConstructorIL.Emit(OpCodes.Ldc_I8, 0);
defaultConstructorIL.Emit(OpCodes.Stfld, version);
当我尝试实例化代理类型的实例时,我得到了无效的程序异常。有人可以解释为什么改变类型会导致这种情况吗?
答案 0 :(得分:5)
问题在于您使用Emit()
的重载需要int
,但ldc.i8
需要long
。
因此,如果您使用以下行,您的代码将正常工作(请注意0L
字面而不是0
):
defaultConstructorIL.Emit(OpCodes.Ldc_I8, 0L);
答案 1 :(得分:0)
http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ldc_i4.aspx的备注部分中的详细信息让我:
defaultConstructorIL.Emit(OpCodes.Ldarg_0);
defaultConstructorIL.Emit(OpCodes.Ldc_I4_0, 0);
defaultConstructorIL.Emit(OpCodes.Conv_I8);
defaultConstructorIL.Emit(OpCodes.Stfld, version);
哪个有用。