Pregunta

Estoy implementando un constructor de un tipo dinámico, pero cuando estoy ejecutando el código que me arroja una excepción que la IL-Código está dañado ( FatalExecutionError ).

IL-Código

La parte de trabajo:

.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

Cuando la adición de los siguientes IL-código se produce el error.Debe tener algo que ver con el código o es algún otro comportamiento extraño que sólo se produce con el código antes de este código.

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

El punto es que las líneas que causa el error ( parece que ellos son la razón para el error ) son sólo un simple as, cuando habla de C#, nada más.Sería genial si alguien tiene una idea para resolver este problema.

La generación de código

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);

Castclass ( Edit )

Me di cuenta de que OpCodes.Castclass no tira el error pero, por supuesto, lanza un runtime-error cuando el tiempo de ejecución está tratando de lanzar un objeto no válido.

Otra cosa loca ( Edición 2 )

Me di cuenta también de que funciona cuando puedo cambiar el pasado Isinst con Castclass funciona sin tirar ningún error.Esto me hace aún más preguntando acerca de este error.Cuando comente las líneas que generan castclass el error está de vuelta otra vez.

¿Fue útil?

Solución

Probé tu código (tuve que cambiar el constructor a MethodAttributes.Public para que funcione) y funcionó perfectamente.Pido disculpas porque esto no es realmente una respuesta, pero quería mostrar el código que utilicé en caso de que indique alguna diferencia que pueda ser útil:

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);
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top