当我运行它时,我当前有以下代码我得到错误代码操作可能会破坏运行时的稳定性(这个我更新的il代码匹配sigil它仍然无法工作)
public static Func<IDataReader, Object> TestMethod<T>()
{
var method = new DynamicMethod("", typeof(Object), new[]
{
typeof ( IDataReader )
});
var il = method.GetILGenerator();
Label whileIf = il.DefineLabel();
Label whileStart = il.DefineLabel();
Label methodEnd = il.DefineLabel();
il.Emit(OpCodes.Newobj, typeof(List<string>).GetConstructor(new Type[0]));
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Br_S, whileIf);
il.MarkLabel(whileStart);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Callvirt, typeof(IDataRecord).GetMethod("GetString"));
il.Emit(OpCodes.Callvirt, typeof(List<string>).GetMethod("Add"));
il.MarkLabel(whileIf);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Callvirt, typeof(IDataReader).GetMethod("Read"));
il.Emit(OpCodes.Brtrue_S, whileStart);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
return (Func<IDataReader, Object>)method.CreateDelegate(typeof(Func<IDataReader, Object>));
}
它是根据以下代码创建的:
public List<string> method(IDataReader dataReader)
{
var result = new List<string>();
while (dataReader.Read())
result.Add(dataReader.GetString(0));
return result;
}
其中生成以下IL代码:
IL_0000: nop
IL_0001: newobj System.Collections.Generic.List<System.String>..ctor
IL_0006: stloc.0 // result
IL_0007: br.s IL_0017
IL_0009: ldloc.0 // result
IL_000A: ldarg.1
IL_000B: ldc.i4.0
IL_000C: callvirt System.Data.IDataRecord.GetString
IL_0011: callvirt System.Collections.Generic.List<System.String>.Add
IL_0016: nop
IL_0017: ldarg.1
IL_0018: callvirt System.Data.IDataReader.Read
IL_001D: stloc.2 // CS$4$0001
IL_001E: ldloc.2 // CS$4$0001
IL_001F: brtrue.s IL_0009
IL_0021: ldloc.0 // result
IL_0022: stloc.1 // CS$1$0000
IL_0023: br.s IL_0025
IL_0025: ldloc.1 // CS$1$0000
IL_0026: ret
我正在IL中编写此代码,因为我最终会扩展代码,动态创建此代码以从TArg填充类型。对不起,我没有更多关于视觉工作室给我的信息。
这是我的sigil代码,它可以正常运行和运行:
var emiter = Emit<Func<IDataReader, List<String>>>.NewDynamicMethod("MyMethod");
var whileIf = emiter.DefineLabel("whileIf");
var whileStart = emiter.DefineLabel("whileStart");
emiter.DeclareLocal(typeof(List<string>), "0");
emiter.NewObject<List<String>>();
emiter.StoreLocal("0");
emiter.Branch(whileIf);
emiter.MarkLabel(whileStart);
emiter.LoadLocal("0");
emiter.LoadArgument(0);
emiter.LoadConstant(0);
emiter.CallVirtual(typeof(IDataRecord).GetMethod("GetString"));
emiter.CallVirtual(typeof(List<string>).GetMethod("Add"));
emiter.MarkLabel(whileIf);
emiter.LoadArgument(0);
emiter.CallVirtual(typeof(IDataReader).GetMethod("Read"));
emiter.BranchIfTrue(whileStart);
emiter.LoadLocal("0");
emiter.Return();
Func<IDataReader, List<string>> result = emiter.CreateDelegate();
Disassembler<Func<IDataReader, List<string>>>.Disassemble( result );
return result;
答案 0 :(得分:2)
这通常意味着堆栈不平衡或错误的调用(静态与虚拟)。我不是在电脑上检查堆栈状态,但是:如果你不确定,我强烈建议使用像“sigil”这样的工具。它是明确设计的,一旦你在发出错误时告诉你,而不是在你以后运行它时。一旦你完成它就会告诉你这个问题。
但这些绝对是错误的方式:
il.Emit( OpCodes.Ldarg_0 );
il.MarkLabel( whileIf );
第一次通过它直接分支到whileIf,你在空堆栈上进行调用。
答案 1 :(得分:0)
当我编写更多IL时,我编写了这些帮助方法,让我创建委托,同时生成调试程序集。使用组件对于运行反射器工具以及PEVerify非常有用。 https://bitbucket.org/mburbea/delegatedproxy/src/483a0120ff845379898ffad790082c62e43efb4e/Utilities/CodeGen.cs?at=master
这是我的实现,我基本上从未在我的各个项目之间进行更改。