Reflection.Emit Generic Base Class Appel de méthode générique
-
05-07-2019 - |
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[] { });
}
}
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.