Comment appeler la méthode à partir d’un MethodCallExpression en c #

J’ai une expression d’appel de méthode et essaie d’appeler la méthode. J’ai trouvé un moyen, mais la récupération des valeurs de paramètre me pose problème, car tous les arguments ne sont pas décrits avec une expression constante.

Expression<Action> = t => t.DoSomething(Par0, Par1, Par2); MethodCallExpression methodCallExpression = selector.Body as MethodCallExpression; // get the information which is needed to invoke the method from the provided // lambda expression. MethodInfo methodInfo = methodCallExpression.Method; object[] arguments = methodCallExpression.Arguments.OfType() .Select(p => p.Value).ToArray(); // invoke the expression on every item within the enumerable foreach (TSource item in source) { methodInfo.Invoke(item, arguments); } 

De plus, j’ai déjà vu d’autres moyens d’invoquer la méthode. Maintenant, je ne sais pas quelle est la bonne façon de le faire.

 var func = expression.Comstack(); var success = func.Invoke(); 

Ma question est donc la suivante: comment puis-je récupérer les valeurs d’argument de la méthode à partir de methodCallExpression.Arguments ?

Ou y a-t-il un moyen plus facile d’atteindre mon objective?

Vous n’avez pas à vous soucier de récupérer les arguments et d’appeler vous-même MethodInfo, vous pouvez laisser .NET le faire pour vous. Tout ce que vous avez à faire est de créer une expression Lambda contenant cette méthode.

par exemple.

 MethodCallExpression expression = GetExpressionSomeHow(); object result = Expression.Lambda(expression).Comstack().DynamicInvoke(); 

C’est ainsi que je traite de toute façon les requêtes nestedes dans mon fournisseur Linq.

EDIT: En fait, il semblerait que vous ayez peut-être déjà une expression LambdaExpression dans la variable de sélection. Dans ce cas, vous devriez pouvoir simplement le comstackr et l’invoquer directement:

 object result = selector.Comstack().DynamicInvoke(); 

Comstackr une expression est une opération très intensive, je ne le ferais donc que si vous envisagez de réutiliser l’expression. Je recommanderais la manière de reflection autrement; vous constaterez qu’il s’exécute plus rapidement. N’appelez jamais expression.Comstack () dans une boucle serrée.

@ Ch00k <- Merci, belle explication. Je voudrais juste ajouter que

 selector.Comstack(); 

vous donne un délégué. Pour une méthode d’instance, vous avez besoin d’une instance sur laquelle appeler cette méthode. Vous transmettez cette instance en tant qu’argument à DynamicInvoke ala

 // Grab the method from MyClass - param1 and param2 are the actual parameters you // want to pass to the method call. Expression> selector = (x => x.MyMethod(param1, param2)); // Create an instance of MyClass to call the method on var myClass = new MyClass(); // Call the method on myClass through DynamicInvoke object returnValue = selector.Comstack().DynamicInvoke(myClass); 

Si vous voulez comstackr votre expression.call en une action ou un func, procédez comme suit:

 var method = typeof(MyType).GetMethod(nameof(MyType.MyMethod), BindingFlags.Public | BindingFlags.Static); var parameter = Expression.Parameter(typeof(ssortingng), "s"); var call = Expression.Call(method, parameter); var lambda = Expression.Lambda>(call, call.Arguments.OfType()); var func = lambda.Comstack(); int result = func("sample ssortingng input"); 

Cela vous permet simplement de faire func.Invoke (“myssortingng”) ou func (“my ssortingng”);

Le secret est que vous devez transmettre les mêmes parameters que lors de la création de Expression.Call. Sinon, vous obtenez une erreur de type “InvalidOperationException”, la variable ‘s’ de type ‘System.Ssortingng’ référencée depuis la scope ” non défini.

Je voudrais essayer ceci pour retourner l’object:

 private static object _getValue(MethodCallExpression expression) { var objectMember = Expression.Convert(expression, typeof(object)); var getterLambda = Expression.Lambda>(objectMember); var getter = getterLambda.Comstack(); return getter(); } 

Il est beaucoup plus rapide d’appeler le suivant:

 LambdaExpression l = Expression.Lambda(Expression.Convert(element, element.Type)); return l.Comstack().DynamicInvoke();