动态类型 - 属性setter上的InvokeMember抛出异常

时间:2015-01-28 22:01:25

标签: c# .net system.reflection

我正在使用以下代码创建基于键/值的类类型:

    /// <summary>
    /// Generate a new class type using the schema info in a list of DataGridHeader
    /// </summary>
    /// <param name="header"></param>
    /// <returns></returns>
    static public Type BuildType(IList<DataGridHeader> header) {
        AppDomain domain = Thread.GetDomain();
        AssemblyName assemblyName = new AssemblyName {Name = "DynamicDataGridDataAsm"};
        AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder dynamicDataGridDataModule = assemblyBuilder.DefineDynamicModule("DynamicDataGridDataModule", "DynamicDataGridDataModule.dll");
        TypeBuilder ivTypeBld = dynamicDataGridDataModule.DefineType("DynamicDataGridData", TypeAttributes.Public);

        foreach (var kvp in header) {
            ImplementProperty(ivTypeBld, kvp.Name, typeof(string));
        }

        ImplementProperty(ivTypeBld, "Value", typeof(string));

        return ivTypeBld.CreateType();
    }

    /// <summary>
    /// Generates propery Get/Set methods for a property by name and type
    /// </summary>
    /// <param name="type"></param>
    /// <param name="propertyName"></param>
    /// <param name="propertyType"></param>
    private static void ImplementProperty(TypeBuilder type, string propertyName, Type propertyType) {
        FieldBuilder field = type.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

        PropertyBuilder property = type.DefineProperty(propertyName, PropertyAttributes.None, propertyType, Type.EmptyTypes);

        MethodBuilder getter = type.DefineMethod("get_" + propertyName, MethodAttributes.Public, propertyType, Type.EmptyTypes);
        ILGenerator getterIL = getter.GetILGenerator();
        getterIL.Emit(OpCodes.Ldarg_0);
        getterIL.Emit(OpCodes.Ldfld, field);
        getterIL.Emit(OpCodes.Ret);

        MethodBuilder setter = type.DefineMethod("set_" + propertyName, MethodAttributes.Public, typeof(void), new Type[] { propertyType });
        ILGenerator setterIL = setter.GetILGenerator();
        setterIL.Emit(OpCodes.Ldarg_0);
        setterIL.Emit(OpCodes.Ldarg_0);
        setterIL.Emit(OpCodes.Ldflda, field);
        setterIL.Emit(OpCodes.Ldarg_1);
        setterIL.Emit(OpCodes.Ldstr, propertyName);
        setterIL.Emit(OpCodes.Call, propertyType);
        setterIL.Emit(OpCodes.Ret);

        property.SetGetMethod(getter);
        property.SetSetMethod(setter);
    }

构建类型后,我尝试使用字典值填充新属性成员:

        static public object GetInstance(Type type, Dictionary<string, string> data) {
            //default construct the new type
            ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes);
            object row = constructorInfo.Invoke(null);

            //Call set on each property
            foreach (var kv in data) {
                try {
//                    PropertyInfo prop = row.GetType().GetProperty(kv.Key, BindingFlags.Public | BindingFlags.Instance);
//                    if (null != prop && prop.CanWrite) {
//                        prop.SetValue(row, kv.Value, null);
//                    }

                    type.InvokeMember(kv.Key,
                        BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
                        Type.DefaultBinder,
                        row,
                        new object[] {kv.Value});
                }
                catch (Exception e) {
                    Console.WriteLine(e);
                }
            }

调用InvokeMember或PropertyInfo.SetValue导致异常

“{System.Reflection.TargetInvocationException:调用目标抛出了异常.---&gt; System.BadImageFormatException:错误的方法标记。    at DynamicDataGridData.set_Value(String)    ---内部异常堆栈跟踪结束---    at System.RuntimeMethodHandle.InvokeMethod(Object target,Object [] arguments,Signature sig,Boolean constructor)    at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,Object [] parameters,Object [] arguments)    在System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder binder,Object []参数,CultureInfo文化)    at System.RuntimeType.InvokeMember(String name,BindingFlags bindingFlags,Binder binder,Object target,Object [] providedArgs,ParameterModifier [] modifiers,CultureInfo culture,String [] namedParams)    at System.Type.InvokeMember(String name,BindingFlags invokeAttr,Binder binder,Object target,Object [] args)    at DSI.MobileClient.Models.DataGridDataTypeBuilder.GetInstance(Type type,Dictionary`2 data)in c:\ DSISource_Global \ v7 \ Development \ Team5 \ DSI.MobileClient \ Models \ DataGridDataTypeBuilder.cs:line 33}“

我一直在调查set属性构建器的.Emit部分中可能出现的问题,但是我还没想到我错过了什么。

调试器显示我正在尝试设置的属性。

**修改

认为这条线不正确:

setterIL.Emit(OpCodes.Call, propertyType);

现在尝试理解复制和粘贴 - 用此替换setter emit可能有效:

    setterIL.Emit(OpCodes.Ldarg_0);
    setterIL.Emit(OpCodes.Ldarg_1);
    setterIL.Emit(OpCodes.Stfld, field);
    setterIL.Emit(OpCodes.Ret);

0 个答案:

没有答案