.NET TypeBuilder-VerificationException:操作可能会破坏运行时的稳定性

.NET TypeBuilder-VerificationException:操作可能会破坏运行时的稳定性,.net,interface,cil,.net,Interface,Cil,我需要在运行时使用TypeBuilder创建一个类型。这种类型应该实现一个特定的接口,这样就可以在编译时统一处理这种动态类型的实例 接口应该返回一个对象数组,其中填充了该类型中特定字段的值 应实现的接口定义如下: public interface ISelectable { object[] GetPrimaryKeysValues(); } 这是我用来为接口生成方法的代码: public static Type BuildTypeFromTable(Table tableToBuil

我需要在运行时使用TypeBuilder创建一个类型。这种类型应该实现一个特定的接口,这样就可以在编译时统一处理这种动态类型的实例

接口应该返回一个对象数组,其中填充了该类型中特定字段的值

应实现的接口定义如下:

public interface ISelectable
{
    object[] GetPrimaryKeysValues();
}
这是我用来为接口生成方法的代码:

public static Type BuildTypeFromTable(Table tableToBuildTypeFrom)
{
    AssemblyBuilder customTypesAssembly =
            AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("CustomTypesAssembly"), AssemblyBuilderAccess.Run);

    ModuleBuilder _moduleBuilder = customTypesAssembly.DefineDynamicModule("CustomTypesModule");

    TypeBuilder customTypeBuilder = _moduleBuilder.DefineType(Guid.NewGuid().ToString(), TypeAttributes.Public | TypeAttributes.Class);

    List<FieldBuilder> primaryKeyFields = new List<FieldBuilder>();

    //create a property for each column in the table
    for (int i = 0; i < tableToBuildTypeFrom.Columns.Count; i++)
    {
        string propertyName = tableToBuildTypeFrom.Columns[i].Name;
        //get a type of a property to create from a first row of the table
        Type propertyType = tableToBuildTypeFrom.GetTypeOfColumnAtIndex(i);

        //each property has to have a field to store its value in
        FieldBuilder backingField = customTypeBuilder.DefineField(propertyName + "_field", propertyType, FieldAttributes.Private);

        //body of a property getter
        MethodBuilder getMethod = customTypeBuilder.DefineMethod(propertyName + "_get", MethodAttributes.Public | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
        ILGenerator getIlGenerator = getMethod.GetILGenerator();
        getIlGenerator.Emit(OpCodes.Ldarg_0);
        getIlGenerator.Emit(OpCodes.Ldfld, backingField);
        getIlGenerator.Emit(OpCodes.Ret);

        ///body of a property setter
        MethodBuilder setMethod = customTypeBuilder.DefineMethod(propertyName + "_set", MethodAttributes.Public | MethodAttributes.HideBySig, null, new Type[] { propertyType });
        ILGenerator setIlGenerator = setMethod.GetILGenerator();
        setIlGenerator.Emit(OpCodes.Ldarg_0);
        setIlGenerator.Emit(OpCodes.Ldarg_1);
        setIlGenerator.Emit(OpCodes.Stfld, backingField);
        setIlGenerator.Emit(OpCodes.Ret);

        PropertyBuilder customProperty = customTypeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, Type.EmptyTypes);
        customProperty.SetGetMethod(getMethod);
        customProperty.SetSetMethod(setMethod);

        //save all primary key columns to avoid iterating over columns all over again
        if (tableToBuildTypeFrom.Columns[i].IsPrimaryKey)
        {
            primaryKeyFields.Add(backingField);
        }
    }

    customTypeBuilder.AddInterfaceImplementation(typeof(ISelectable));

    MethodBuilder getPrimaryKeysMethod = customTypeBuilder.DefineMethod("GetPrimaryKeysValues", MethodAttributes.Public | MethodAttributes.Virtual, typeof(object[]), null);
    ILGenerator getPrimaryKeysMethodIlGenerator = getPrimaryKeysMethod.GetILGenerator();

    getPrimaryKeysMethodIlGenerator.DeclareLocal(typeof(object[]));
    getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Ldc_I4, primaryKeyFields.Count);
    getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Newarr, typeof(object));
    getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Stloc_0);

    for (int i = 0; i < primaryKeyFields.Count; i++)
    {
        getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Ldloc_0);
        getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Ldc_I4, i);

        getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Ldarg_0);
        getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Ldfld, primaryKeyFields[i]);

        getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Stelem_Ref);
    }

    getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Ldloc_0);
    getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Ret);

    MethodInfo s = typeof(ISelectable).GetMethod("GetPrimaryKeysValues");
    customTypeBuilder.DefineMethodOverride(getPrimaryKeysMethod, s);

    return customTypeBuilder.CreateType();
}
公共静态类型BuildTypeFromTable(Table Table到buildtypefrom)
{
部件生成器自定义类型部件=
AppDomain.CurrentDomain.DefinedDynamicAssembly(新的AssemblyName(“CustomTypesAssembly”)、AssemblyBuilderAccess.Run);
ModuleBuilder _ModuleBuilder=customTypesAssembly.DefinedDynamicModule(“CustomTypesModule”);
TypeBuilder customTypeBuilder=_moduleBuilder.DefineType(Guid.NewGuid().ToString(),TypeAttributes.Public | TypeAttributes.Class);
List primaryKeyFields=新列表();
//为表中的每列创建属性
for(int i=0;i
该方法的生成方式取自

现在的问题是,每次我尝试调用GetPrimaryKeysValues方法时,都会抛出带有消息“操作可能会破坏运行时稳定”的VerificationException。我不知道是什么引起的。有人能帮忙吗


谢谢大家!

您没有声明局部变量,但使用了它(
Stloc\u 0
Ldloc\u 0

在生成IL代码之前插入此项:

getPrimaryKeysMethodIlGenerator.DeclareLocal(typeof(object[]));

stelem.ref
操作码将对象引用存储到数组中。这意味着,如果您有值类型的字段(例如,
int
s),则需要确保在将其存储到数组中之前将其装箱。因此,您应该添加如下内容

if (primaryKeyFields[i].FieldType.IsValueType) {
    getPrimaryKeysMethodIlGenerator.Emit(OpCodes.Box, primaryKeyFields[i].FieldType);
}
紧靠
stelem.ref
指令之前


另外,尽管这不会导致验证异常,但请注意,属性的方法名称应该是
get{Name}
set{Name}
,而不是
{Name}get
{Name}set
,我已经添加了您的代码行,但它仍然不起作用。不断抛出相同的异常。我已经更新了我最初的帖子以反映你的建议,不过,这肯定是正确的。谢谢大家!@洛塔请把全部代码都写出来。因为如果我把局部变量添加到你给它的部分,它就开始工作了。@Lotar我感觉你的堆栈不平衡,你有更多的推送(ldXXX)然后是弹出(其他)我编辑了我的原始帖子,并在里面放了一个生成类型的完整方法。谢谢,这就成功了!我只需要稍微修改一下您的代码——为了让它正常工作,Box操作码的类型参数应该是typeof(primaryKeyFields[I].Fiel)