1

我在生成的代理中使用以下代码进行版本跟踪:

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);

当我尝试实例化代理类型的实例时,我得到一个无效的程序异常。有人能解释一下为什么改变类型会导致这种情况吗?

4

2 回答 2

5

问题是您正在使用需要 a 的重载Emit()intldc.i8需要long.

因此,如果您使用以下行,您的代码将正常工作(注意0L文字而不是0):

defaultConstructorIL.Emit(OpCodes.Ldc_I8, 0L);
于 2013-07-02T15:42:29.480 回答
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);

哪个有效。

于 2013-07-02T15:19:27.367 回答