Question

Je sous-classe dynamiquement un type générique (remplir son contrat) qui possède une méthode générique. J'essaie d'appeler cette méthode générique, mais l'assembly que je produis contient des erreurs. Reflector se bloque lors de la tentative d'ouverture de l'assembly et cet extrait de code ne s'exécute pas.

L'exception que je reçois est la suivante:

Une tentative de chargement d'un programme avec un format incorrect a été effectuée. (Exception de HRESULT: 0x8007000B)

Toute aide serait appréciée. Je vais installer PEVerify pour examiner le code généré.

using System;
using System.Reflection;
using System.Reflection.Emit;

public class TestClass<TFirst>
{
    public void TestMethod<TSecond>()
    {
        Console.WriteLine("It works");
    }
}
public class Program
{
    static void Main(string[] args)
    {
        // create a dynamic assembly and module 
        var assemblyName = new AssemblyName("DynamicAssembly");
        var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
        var module = assemblyBuilder.DefineDynamicModule("DynamicAssembly.dll");

        // public class Voodoo.Dynamic.Class : TestClass<object>
        var testClass = typeof(TestClass<>);
        var testClassOfObject = testClass.MakeGenericType(typeof(object));
        var typeBuilder = module.DefineType(
            "Voodoo.Dynamic.Class",
            TypeAttributes.Public | TypeAttributes.Class,
            testClassOfObject);

        // public void Run()
        var methodBuilder = typeBuilder.DefineMethod("Run", MethodAttributes.Public);

        // this.TestMethod<int>();
        var testGeneric = testClass.GetMethod("TestMethod").MakeGenericMethod(typeof(int));
        var il = methodBuilder.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0); // load this
        il.Emit(OpCodes.Call, testGeneric);
        il.Emit(OpCodes.Ret);

        // bake it
        var classType = typeBuilder.CreateType();

        assemblyBuilder.Save("DynamicAssembly.dll");

        // var instance = new Voodoo.Dynamic.Class();
        var instance = Activator.CreateInstance(classType);

        // instance.Run();
        classType.GetMethod("Run").Invoke(instance, new object[] { });
    }
}
Était-ce utile?

La solution

Au lieu de:

var testGeneric = testClass
    .GetMethod("TestMethod")
    .MakeGenericMethod(typeof(int));

Vous avez besoin de:

var testGeneric = testClassOfObject
    .GetMethod("TestMethod")
    .MakeGenericMethod(typeof(int));

car testClass est un type de classe générique ouvert et si vous essayez d'appeler une méthode, elle planterait.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top