Im пытается сгенерировать новый класс/объект во время выполнения.Reflection.Emit throws BadImageFormatException
После прочтения How to create a private property using PropertyBuilder, мне удалось реализовать все, и все так, как будто оно мне нужно.
Но как только им пытаются создать экземпляр моего нового объекта, им получать BadImageFormatException
Это, кажется, подобная проблема, но неразрешенный Is there any way to instrument 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;}
любая помощь о том, как создать экземпляр моего недавно созданного типа ParamRow
.
Бонус-вопрос: Почему существует BadImageFormatException
?
Дополнительная информация:
- .Net Framework 4.6.1-
- Compiler-цель x86
- Никогда не делал
Reflection.Emit
до того
Я собираюсь посмотреть на него в отладчик и посмотреть, если я могу обнаружить ошибку, но: если вы хотите хороший способ избежать их и получать хорошие сообщения об ошибках, попробуйте [Сигила] (HTTPS: //www.nuget.org/packages/Sigil /) - это оболочка вокруг испускания IL (но концептуально такая же) и предназначена для того, чтобы затруднить ее выполнение (или, по крайней мере, легко понять, почему он потерпел неудачу) –