Frage

Ich implementiere einen Konstruktor für einen dynamischen Typ, aber wenn ich den Code ausführe, wird eine Ausnahme ausgegeben, dass der IL-Code beschädigt ist ( FatalExecutionError ).

IL-Kode

Arbeitsteil:

.method assembly specialname rtspecialname 
instance void .ctor (
    object '',
    object '',
    string ''
) cil managed 
{
// Method begins at RVA 0xa370
// Code size 36 (0x24)
.maxstack 2
.locals init (
    [0] class [mscorlib]System.Collections.IList,
    [1] class [mscorlib]System.Collections.IList
)

IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld object HIDDEN.PropertyComparison::_Object0
IL_0007: ldarg.0
IL_0008: ldarg.2
IL_0009: stfld object HIDDEN.PropertyComparison::_Object1
IL_000e: ldarg.0
IL_000f: ldarg.3
IL_0010: stfld string HIDDEN.PropertyComparison::_Name
// Return is here normally when not using the following code

Beim Hinzufügen des folgenden IL-Codes tritt der Fehler auf.Es muss etwas mit dem Code zu tun haben oder es ist ein anderes seltsames Verhalten, das nur mit dem Code vor diesem Code auftritt.

IL_0015: ldarg.1
IL_0016: isinst [mscorlib]System.Collections.IList
IL_001b: stloc.0
IL_001c: ldarg.2
IL_001d: isinst [mscorlib]System.Collections.IList
IL_0022: stloc.1
IL_0023: ret
} // end of method PropertyComparison::.ctor

Der Punkt ist, dass die Linien, die den Fehler verursachen (es scheint, dass sie der Grund für den Fehler sind), nur eine einfache sind as, wenn man von C # spricht, nichts weiter.Wäre toll, wenn jemand eine Idee hat, dieses Problem zu lösen.

Code generieren

PropertyComparisonType = _Module.DefineType("HIDDEN.PropertyComparison", TypeAttributes.Public, typeof(Object));
FieldBuilder object0Field = PropertyComparisonType.DefineField("_Object0", typeof(Object), FieldAttributes.Private);
FieldBuilder object1Field = PropertyComparisonType.DefineField("_Object1", typeof(Object), FieldAttributes.Private);
FieldBuilder equalField = PropertyComparisonType.DefineField("_Equal", typeof(Boolean), FieldAttributes.Private);
FieldBuilder nameField = PropertyComparisonType.DefineField("_Name", typeof(String), FieldAttributes.Private);
FieldBuilder childsField = PropertyComparisonType.DefineField("_Childs", typeof(IEnumerable<>).MakeGenericType(PropertyComparisonType), FieldAttributes.Private);

PropertyBuilder object0Property = PropertyComparisonType.DefineProperty("Object0", object0Field, setter: false);
PropertyBuilder object1Property = PropertyComparisonType.DefineProperty("Object1", object1Field, setter: false);
PropertyBuilder equalProperty = PropertyComparisonType.DefineProperty("Equal", equalField, setter: false);
PropertyBuilder nameProperty = PropertyComparisonType.DefineProperty("Name", nameField, setter: false);
PropertyBuilder childsProperty = PropertyComparisonType.DefineProperty("Childs", childsField, setter: false);

PropertyComparisonConstructor = PropertyComparisonType.DefineConstructor(MethodAttributes.Assembly, CallingConventions.Standard, new[] { typeof(Object), typeof(Object), typeof(String) });
ILGenerator il = PropertyComparisonConstructor.GetILGenerator();


il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Stfld, object0Field);

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Stfld, object1Field);

il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_3);
il.Emit(OpCodes.Stfld, nameField);

LocalBuilder localList0 = il.DeclareLocal(typeof(IList));
LocalBuilder localList1 = il.DeclareLocal(typeof(IList));

il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Isinst, typeof(IList));
il.Emit(OpCodes.Stloc, localList0);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Isinst, typeof(IList));
il.Emit(OpCodes.Stloc, localList1);

Castklasse ( Bearbeiten )

Das ist mir aufgefallen OpCodes.Castclass löst den Fehler nicht aus, löst aber natürlich einen Laufzeitfehler aus, wenn die Laufzeit versucht, ein ungültiges Objekt umzuwandeln.

Eine andere verrückte Sache ( Bearbeiten 2 )

Mir ist auch aufgefallen, dass es funktioniert, wenn ich das letzte austausche Isinst mit Castclass es funktioniert ohne Fehler zu werfen.Das wundert mich noch mehr über diesen Fehler.Wenn Sie die Zeilen auskommentieren, die castclass generieren, ist der Fehler wieder da.

War es hilfreich?

Lösung

Ich habe Ihren Code ausprobiert (musste den Konstruktor ändern in MethodAttributes.Public um es zum Laufen zu bringen) und es funktionierte einwandfrei.Ich entschuldige mich, dass dies nicht wirklich eine Antwort ist, wollte aber den Code zeigen, den ich verwendet habe, falls er auf Unterschiede hinweist, die hilfreich sein könnten:

class Program
{
    static void Main(string[] args)
    {
        var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave);
        var _Module = assembly.DefineDynamicModule("fooModule");

        var PropertyComparisonType = _Module.DefineType("HIDDEN.PropertyComparison", TypeAttributes.Public, typeof(Object));
        FieldBuilder object0Field = PropertyComparisonType.DefineField("_Object0", typeof(Object), FieldAttributes.Private);
        FieldBuilder object1Field = PropertyComparisonType.DefineField("_Object1", typeof(Object), FieldAttributes.Private);
        FieldBuilder equalField = PropertyComparisonType.DefineField("_Equal", typeof(Boolean), FieldAttributes.Private);
        FieldBuilder nameField = PropertyComparisonType.DefineField("_Name", typeof(String), FieldAttributes.Private);
        FieldBuilder childsField = PropertyComparisonType.DefineField("_Childs", typeof(IEnumerable<>).MakeGenericType(PropertyComparisonType), FieldAttributes.Private);

        var PropertyComparisonConstructor = PropertyComparisonType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(Object), typeof(Object), typeof(String) });
        ILGenerator il = PropertyComparisonConstructor.GetILGenerator();


        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Stfld, object0Field);

        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldarg_2);
        il.Emit(OpCodes.Stfld, object1Field);

        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldarg_3);
        il.Emit(OpCodes.Stfld, nameField);

        LocalBuilder localList0 = il.DeclareLocal(typeof(IList));
        LocalBuilder localList1 = il.DeclareLocal(typeof(IList));

        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Isinst, typeof(IList));
        il.Emit(OpCodes.Stloc, localList0);
        il.Emit(OpCodes.Ldarg_2);
        il.Emit(OpCodes.Isinst, typeof(IList));
        il.Emit(OpCodes.Stloc, localList1);
        il.Emit(OpCodes.Ret);

        var type = PropertyComparisonType.CreateType();

        var list1 = new List<string>();
        var list2 = new List<string>();
        var s = "prop";
        var instance = Activator.CreateInstance(type, list1, list2, s);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top