Créer DynamicMethod pour atsortingbuer une valeur à une propriété?

Ceci est un exercice d’apprentissage. J’ai créé une méthode qui prend un Foo et une chaîne et définit la propriété A. J’ai utilisé le désassemblage de Reflector pour créer le code suivant. Le déassembly ressemble à ceci:

.method private hidebysig static void Spork(class ConsoleTesting.Foo f, ssortingng 'value') cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldarg.1 L_0002: callvirt instance void ConsoleTesting.Foo::set_A(ssortingng) L_0007: ret } 

Ok, j’ai donc modélisé mon code d’émission après cela:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Reflection.Emit; namespace ConsoleTesting { class Foo { public ssortingng A { get; set; } } class Program { static Action GenMethodAssignment(ssortingng propName) { MethodInfo setMethod = typeof(Foo).GetMethod("get_" + propName); if (setMethod == null) throw new InvalidOperationException("no property setter available"); Type[] argTypes = new Type[] { typeof(Foo), typeof(Ssortingng) }; DynamicMethod method = new DynamicMethod("__dynamicMethod_Set_" + propName, null, argTypes, typeof(Program)); ILGenerator IL = method.GetILGenerator(); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Ldarg_1); IL.Emit(OpCodes.Callvirt, setMethod); IL.Emit(OpCodes.Ret); method.DefineParameter(1, ParameterAtsortingbutes.In, "instance"); method.DefineParameter(2, ParameterAtsortingbutes.In, "value"); Action retval = (Action)method.CreateDelegate(typeof(Action)); return retval; } static void Main(ssortingng[] args) { Foo f = new Foo(); var meth = GenMethodAssignment("A"); meth(f, "jason"); Console.ReadLine(); } } 

Je reçois cette exception:

 JIT Comstackr encountered an internal limitation. 

Qu’est-ce que le krunk signifie-t-il et comment puis-je le réparer?

MODIFIER:

Je pensais que c’était peut-être parce que la méthode cible était privée, mais je n’en suis pas si sûr. A partir de la page DynamicMethod MSDN :

L’exemple de code suivant crée un DynamicMethod associé logiquement à un type. Cette association lui donne access aux membres privés de ce type.

Question intéressante. Tout d’abord, il y a peu de choses que vous puissiez faire. Si vous souhaitez uniquement un délégué pour le créateur, vous pouvez utiliser Delegate.CreateDelegate .

 Delegate.CreateDelegate(typeof(Action),typeof(Foo).GetProperty("A").GetSetMethod()) as Action; 

Si vous utilisez .NET 3.5+, vous pouvez utiliser des arbres d’expression et je vous recommande fortement de les apprendre via DynamicMethod, leur utilisation est limitée dans .NET 3.5 et presque aucun .NET 4. (TypeBuilder rest néanmoins très utile).

 var targetExpression = Expression.Parameter(typeof(Foo),"target"); var valueExpression = Expression.Parameter(typeof(ssortingng),"value"); var expression = Expression.Lambda>( Expression.Call( targetExpression, typeof(Foo).GetProperty("A").GetSetMethod(), valueExpression ), targetExpression, valueExpression ); 

Dans .NET 4, vous pouvez écrire un peu plus joli en utilisant Expression.Assign , mais ce n’est pas beaucoup mieux.

Enfin, si vous voulez vraiment le faire en IL, cela fonctionne.

  DynamicMethod method = new DynamicMethod("Setter", typeof(void), new[] { typeof(Foo), typeof(ssortingng) }, true); var ilgen = method.GetILGenerator(); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Callvirt, typeof(Foo).GetProperty("A").GetSetMethod()); ilgen.Emit(OpCodes.Ret); var action = method.CreateDelegate(typeof(Action)) as Action; 

Je pense que votre problème est que vous appelez actuellement la méthode set. En fait, getMethod l’erreur est sur cette ligne :: MethodInfo setMethod = typeof(Foo).GetMethod("get_" + propName);

Je n’ai jamais atsortingbué d’atsortingbuts de parameters, mais cela peut également être un problème.

Eh bien, j’ai compris. En changeant

 IL.Emit(OpCodes.Callvirt, setMethod); 

à

 IL.Emit(OpCodes.Call, setMethod); 

corrigé Je ne sais pas pourquoi le déassembly a montré CallVirt, mais hein.

Sur quelle version de .NET cela doit-il fonctionner? Comstackr un délégué à partir d’un arbre d’expression serait beaucoup plus facile.