Ich versuche, eine neue Klasse/Objekt zur Laufzeit zu generieren.Reflection.Emit wirft BadImageFormatException
Nachdem ich How to create a private property using PropertyBuilder gelesen habe, habe ich es geschafft alles zu implementieren und alles ist wie ich es brauche.
Aber sobald im Versuch, mein neues Objekt instanziieren, im ein BadImageFormatException
Empfang Dies scheint ein ähnliches Problem zu sein, aber ungelöst Is there any way to instrument System.Reflection.Emit?
Hier meinen Code:
Field:
internal class Field {
public string FieldName;
public Type FieldType;
public string Value;
}
Generator-Code:
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);
The Magic
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;}
Jede Hilfe ist willkommen, wie meine neu erstellte Typ ParamRow
instanziieren.
Bonus-Frage: Warum gibt es eine BadImageFormatException
?
Zusätzliche Information:
- .Net-Framework-4.6.1
- Compiler-Ziel ist x86
- Nie hat jemals
Reflection.Emit
vor
Ich bin über einen Blick auf sie in einem Debugger haben, und sehen, ob ich den Fehler erkennen kann, aber: wenn Sie eine gute Art und Weise wollen sie zu vermeiden und eine gute Fehlermeldungen bekommen, versuchen [Siegel] (https: //www.nuget.org/packages/Sigil /) - es ist ein Wrapper um IL emittieren (aber konzeptionell das gleiche), und ist so konzipiert, dass es schwer zu scheitern (oder zumindest, einfach herauszufinden, warum es gescheitert ist) –