簡體   English   中英

Reflection.Emit拋出BadImageFormatException

[英]Reflection.Emit throws BadImageFormatException

我試圖在運行時生成一個新的類/對象。

在閱讀了如何使用PropertyBuilder創建私有財產之后 ,我設法實現了一切,一切都像我需要的。

但是,一旦我試圖實例化我的新對象,我就會收到BadImageFormatException

這似乎是一個類似的問題,但尚未解決是否有任何方法可以檢測System.Reflection.Emit?

這是我的代碼:

領域:

internal class Field {
      public string FieldName;
      public Type FieldType;
      public string Value;
    }

發電機碼:

var xx = new List<Field>(new[] { new Field { FieldName = "Name", FieldType = typeof(string), Value = "Hello World" },
        new Field { FieldName = "Id", FieldType = typeof(int), Value = "1" } });
      this.DoVodoo(xx);

魔術

private dynamic DoVodoo(IEnumerable<Field> fields) {
      var aName = new AssemblyName("DynamicAssemblyExample");
      var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndSave);

      var mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");

      // Create class with all needed Properties
      var tb = mb.DefineType("ParamRow", TypeAttributes.Public, typeof(object));
      foreach (var field in fields) {
        var pb = tb.DefineProperty(field.FieldName, PropertyAttributes.None, CallingConventions.HasThis, field.FieldType, null);

        var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
        // Define the "get" accessor method for the Property.
        var custNameGetPropMthdBldr = tb.DefineMethod($"get_{field.FieldName}", getSetAttr, typeof(string), Type.EmptyTypes);

        var custNameGetIL = custNameGetPropMthdBldr.GetILGenerator();

        custNameGetIL.Emit(OpCodes.Ldarg_0);
        custNameGetIL.Emit(OpCodes.Ldfld, custNameGetPropMthdBldr);
        custNameGetIL.Emit(OpCodes.Ret);

        // Define the "set" accessor method for CustomerName.
        var custNameSetPropMthdBldr = tb.DefineMethod($"set_{field.FieldName}", getSetAttr, null, new[] { typeof(string) });

        var custNameSetIL = custNameSetPropMthdBldr.GetILGenerator();

        custNameSetIL.Emit(OpCodes.Ldarg_0);
        custNameSetIL.Emit(OpCodes.Ldarg_1);
        //custNameSetIL.Emit(OpCodes.Stfld, custNameGetPropMthdBldr);
        custNameSetIL.Emit(OpCodes.Stfld, custNameSetPropMthdBldr);
        custNameSetIL.Emit(OpCodes.Ret);

        // Last, we must map the two methods created above to our PropertyBuilder to 
        // their corresponding behaviors, "get" and "set" respectively. 
        pb.SetGetMethod(custNameGetPropMthdBldr);
        pb.SetSetMethod(custNameSetPropMthdBldr);
      }

      var finalType = tb.CreateType();

      var result = new List<object>();

      foreach (var field in fields) {
        var inst = ab.CreateInstance(finalType.Name);
        finalType.GetProperty(field.FieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).SetValue(inst, field.Value); //<-- Here comes the trouble
        result.Add(inst);
      }
      return result;}

感謝您提供有關如何實例化我新創建的Type ParamRow

獎勵問題:為什么會有BadImageFormatException

附加信息:

  • .Net框架4.6.1
  • 編譯器目標是x86
  • 從來沒有做過Reflection.Emit

重要的是您收到的異常的.Message

字段令牌超出范圍。

這表明您不了解要在ldfld / stfld使用哪個字段-這是因為要向其傳遞方法令牌( custNameGetPropMthdBldr / custNameSetPropMthdBldr )而不是字段令牌。

您需要定義和使用一個字段:

var fb = tb.DefineField("__" + field.FieldName, field.FieldType, FieldAttributes.Private);
// ...
custNameGetIL.Emit(OpCodes.Ldarg_0);
custNameGetIL.Emit(OpCodes.Ldfld, fb);
custNameGetIL.Emit(OpCodes.Ret);
// ...
custNameSetIL.Emit(OpCodes.Ldarg_0);
custNameSetIL.Emit(OpCodes.Ldarg_1);
custNameSetIL.Emit(OpCodes.Stfld, fb);
custNameSetIL.Emit(OpCodes.Ret);

還要注意,通過反射創建對象時,使用Type比使用名稱更有效。 這工作正常:

var inst = Activator.CreateInstance(finalType);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM