我正在为动态类型实现构造函数,但当我执行代码时,它会引发一个异常,即IL代码已损坏(FatalExecutionError
)。
IL代码
工作部分:
.method assembly specialname rtspecialname
instance void .ctor (
object '',
object '',
string ''
) cil managed
{
// Method begins at RVA 0xa370
// Code size 36 (0x24)
.maxstack 2
.locals init (
[0] class [mscorlib]System.Collections.IList,
[1] class [mscorlib]System.Collections.IList
)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld object HIDDEN.PropertyComparison::_Object0
IL_0007: ldarg.0
IL_0008: ldarg.2
IL_0009: stfld object HIDDEN.PropertyComparison::_Object1
IL_000e: ldarg.0
IL_000f: ldarg.3
IL_0010: stfld string HIDDEN.PropertyComparison::_Name
// Return is here normally when not using the following code
添加以下IL代码时,会发生错误。它一定与代码有关,或者是其他一些奇怪的行为,只发生在该代码之前的代码中。
IL_0015: ldarg.1
IL_0016: isinst [mscorlib]System.Collections.IList
IL_001b: stloc.0
IL_001c: ldarg.2
IL_001d: isinst [mscorlib]System.Collections.IList
IL_0022: stloc.1
IL_0023: ret
} // end of method PropertyComparison::.ctor
关键是导致错误的行(似乎它们是错误的原因)只是一个简单的as
,当谈到C#时,仅此而已。如果有人有解决这个问题的想法,那就太好了。
正在生成代码
PropertyComparisonType = _Module.DefineType("HIDDEN.PropertyComparison", TypeAttributes.Public, typeof(Object));
FieldBuilder object0Field = PropertyComparisonType.DefineField("_Object0", typeof(Object), FieldAttributes.Private);
FieldBuilder object1Field = PropertyComparisonType.DefineField("_Object1", typeof(Object), FieldAttributes.Private);
FieldBuilder equalField = PropertyComparisonType.DefineField("_Equal", typeof(Boolean), FieldAttributes.Private);
FieldBuilder nameField = PropertyComparisonType.DefineField("_Name", typeof(String), FieldAttributes.Private);
FieldBuilder childsField = PropertyComparisonType.DefineField("_Childs", typeof(IEnumerable<>).MakeGenericType(PropertyComparisonType), FieldAttributes.Private);
PropertyBuilder object0Property = PropertyComparisonType.DefineProperty("Object0", object0Field, setter: false);
PropertyBuilder object1Property = PropertyComparisonType.DefineProperty("Object1", object1Field, setter: false);
PropertyBuilder equalProperty = PropertyComparisonType.DefineProperty("Equal", equalField, setter: false);
PropertyBuilder nameProperty = PropertyComparisonType.DefineProperty("Name", nameField, setter: false);
PropertyBuilder childsProperty = PropertyComparisonType.DefineProperty("Childs", childsField, setter: false);
PropertyComparisonConstructor = PropertyComparisonType.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, new[] { typeof(Object), typeof(Object), typeof(String) });
ILGenerator il = PropertyComparisonConstructor.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, object0Field);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Stfld, object1Field);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_3);
il.Emit(OpCodes.Stfld, nameField);
LocalBuilder localList0 = il.DeclareLocal(typeof(IList));
LocalBuilder localList1 = il.DeclareLocal(typeof(IList));
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Isinst, typeof(IList));
il.Emit(OpCodes.Stloc, localList0);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Isinst, typeof(IList));
il.Emit(OpCodes.Stloc, localList1);
Castclass(编辑)
我注意到OpCodes.Castclass
不会抛出错误,但当运行时试图抛出无效对象时,当然会抛出运行时错误。
另一件疯狂的事(编辑2)
我还注意到,当我用Castclass
交换最后一个Isinst
时,它可以工作,不会引发任何错误。这让我更加怀疑这个错误。当注释掉生成castclass的行时,错误再次出现。
我尝试了您的代码(必须将构造函数更改为MethodAttributes.Public
才能使其工作),它工作得非常完美。我很抱歉这不是一个真正的答案,但我想展示我使用的代码,以防它指向任何可能有帮助的差异:
class Program
{
static void Main(string[] args)
{
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave);
var _Module = assembly.DefineDynamicModule("fooModule");
var PropertyComparisonType = _Module.DefineType("HIDDEN.PropertyComparison", TypeAttributes.Public, typeof(Object));
FieldBuilder object0Field = PropertyComparisonType.DefineField("_Object0", typeof(Object), FieldAttributes.Private);
FieldBuilder object1Field = PropertyComparisonType.DefineField("_Object1", typeof(Object), FieldAttributes.Private);
FieldBuilder equalField = PropertyComparisonType.DefineField("_Equal", typeof(Boolean), FieldAttributes.Private);
FieldBuilder nameField = PropertyComparisonType.DefineField("_Name", typeof(String), FieldAttributes.Private);
FieldBuilder childsField = PropertyComparisonType.DefineField("_Childs", typeof(IEnumerable<>).MakeGenericType(PropertyComparisonType), FieldAttributes.Private);
var PropertyComparisonConstructor = PropertyComparisonType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(Object), typeof(Object), typeof(String) });
ILGenerator il = PropertyComparisonConstructor.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, object0Field);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Stfld, object1Field);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_3);
il.Emit(OpCodes.Stfld, nameField);
LocalBuilder localList0 = il.DeclareLocal(typeof(IList));
LocalBuilder localList1 = il.DeclareLocal(typeof(IList));
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Isinst, typeof(IList));
il.Emit(OpCodes.Stloc, localList0);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Isinst, typeof(IList));
il.Emit(OpCodes.Stloc, localList1);
il.Emit(OpCodes.Ret);
var type = PropertyComparisonType.CreateType();
var list1 = new List<string>();
var list2 = new List<string>();
var s = "prop";
var instance = Activator.CreateInstance(type, list1, list2, s);
}
}