Bonjour,
Je me lance dans l'IL.
Je génère un type, avec un constructeur et une méthode, le but étant de créer une classe implémentant une interface et de rediriger les appels aux méthodes implémentées
J'arrive bien a créer le type, j'arrive à appeler le constructeur qui remplie des variables privées avec les paramètres.
Par contre quand j'appelle la méthode générée j'obtiens
Tentative de chargement d’un programme de format incorrect. (Exception de HRESULT : 0x8007000B)
environnement
dll en .net standard 2.0
exe en .net framework 4.7.2
je ne maitrise pas l'IL donc j'ai écris une méthode pour un cas donné et j'ai regardé avec JustDecompile l'IL généré, tenté de le comprendre et de l'adapter à mon cas.
Je dois implémenter une interface, donc je fais un for each sur les méthodes de l'interface et j'essaye de créer la méthode avec le code de redirection
les méthodes pouvant avoir des paramètres divers et ont un retour de type Task<T>
signature de la méthode générique que je veux appeler par tout les implémenteurs :
Code : Sélectionner tout - Visualiser dans une fenêtre à part internal async static Task<T> MethodeGenerique <T>(ClasseQuiSaitGerer c, string interfaceName, string methodName, string parametersSignature, params object[] parameters)question subsidiaire, j'ai cru voir qu'avant le Stelem_Ref il y a parfois un box quand c'est des valuetype et que nullable<bool> avait un box aussi (!?)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 foreach (var m in type.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)) { var mthBuilder = typeBuilder.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Final | MethodAttributes.NewSlot, m.ReturnType, m.GetParameters().Select(pi => pi.ParameterType).ToArray()); // ici j'ai essayé aussi sans final newslot et hide var mthIl = mthBuilder.GetILGenerator(); var nbParameters = m.GetParameters().Count(); mthIl.Emit(OpCodes.Ldarg, 0); mthIl.Emit(OpCodes.Ldfld, fieldBuilder); // ma variable privée (_c) mthIl.Emit(OpCodes.Ldstr, interfaceName); mthIl.Emit(OpCodes.Ldstr, m.Name); mthIl.Emit(OpCodes.Ldc_I4, nbParameters); mthIl.Emit(OpCodes.Newarr, typeof(object)); var parametersSignature = ""; for (int i = 0; i < nbParameters; i++) { mthIl.Emit(OpCodes.Dup); // le Dup j'ai pas trop compris ce qu'il fait, et je sais pas s'il va là ou après le Stelemtn_Ref, j'ai essayé les 2 mthIl.Emit(OpCodes.Ldc_I4, i); mthIl.Emit(OpCodes.Ldarg, i + 1); mthIl.Emit(OpCodes.Stelem_Ref); parametersSignature += m.GetParameters()[i].ParameterType.FullName + "||"; } if (parametersSignature.Length > 0) parametersSignature.RemoveEndingChars(2); // supression du || en trop à la fin mthIl.Emit(OpCodes.Ldstr, parametersSignature); MethodInfo mthToCall = typeof(ClasseDeRedirection).GetMethod(nameof(ClasseDeRedirection.MethodeGenerique), BindingFlags.NonPublic | BindingFlags.Static); mthIl.EmitCall(OpCodes.Call, mthToCall, null); mthIl.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(mthBuilder, m); }
mais ce n'est pas mon cas dans mon 1er essai, la seule méthode de l'interface étant Task<bool> Test1 (Class1 c);question subsidiaire 2, sur les opcode parfois ca parle de push sur la stack et parfois de l'evaluation stack, ce sont les même stack ou 2 différentes ?
Partager