Obtenir le nom d'une méthode à l'aide d'une expression

Obtenir le nom d'une méthode à l'aide d'une expression
x => x.DoSomething

Afin de rendre cela compilable, je ne vois que deux façons :

  1. Allez de manière non générique et spécifiez son paramètre comme Action<string, string>
  2. Spécifiez Action<string, string> en tant que délégué cible, saisissez vous-même :GetMethodInfo<IMyInteface>(x => new Action<string,string>(x.DoSomething))

si vous êtes d'accord pour utiliser le second, qui vous permet d'omettre des arguments, vous pouvez écrire votre GetMethodInfo méthode comme suit :

    MemberInfo GetMethodInfo<T>(Expression<Func<T, Delegate>> expression)
    {
        var unaryExpression = (UnaryExpression) expression.Body;
        var methodCallExpression = (MethodCallExpression) unaryExpression.Operand;
        var methodInfoExpression = (ConstantExpression) methodCallExpression.Arguments.Last();
        var methodInfo = (MemberInfo) methodInfoExpression.Value;
        return methodInfo;
    }

Cela fonctionne pour votre interface, mais une généralisation sera probablement nécessaire pour que cela fonctionne avec n'importe quelle méthode, c'est à vous de décider.


Ce qui suit est compatible avec .NET 4.5 :

public static string MethodName(LambdaExpression expression)
{
    var unaryExpression = (UnaryExpression)expression.Body;
    var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
    var methodCallObject = (ConstantExpression)methodCallExpression.Object;
    var methodInfo = (MethodInfo)methodCallObject.Value;

    return methodInfo.Name;
}

Vous pouvez l'utiliser avec des expressions comme x => x.DoSomething , cependant, cela nécessiterait un encapsulage dans des méthodes génériques pour différents types de méthodes.

Voici une version rétrocompatible :

private static bool IsNET45 = Type.GetType("System.Reflection.ReflectionContext", false) != null;

public static string MethodName(LambdaExpression expression)
{
    var unaryExpression = (UnaryExpression)expression.Body;
    var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
    if (IsNET45)
    {
        var methodCallObject = (ConstantExpression)methodCallExpression.Object;
        var methodInfo = (MethodInfo)methodCallObject.Value;
        return methodInfo.Name;
    }
    else
    {
        var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
        var methodInfo = (MemberInfo)methodInfoExpression.Value;
        return methodInfo.Name;
    }
}

Vérifiez cet exemple de code sur Ideone.Notez qu'Ideone n'a pas .NET 4.5.


Le problème avec ceci est que x.DoSomething représente un groupe de méthodes. Et vous devez d'une manière ou d'une autre spécifier explicitement en quel type de délégué voulez-vous convertir ce groupe de méthodes, afin que le bon membre du groupe puisse être sélectionné. Et peu importe si ce groupe ne contient qu'un seul membre.

Le compilateur pourrait en déduire que vous voulez dire celui-là, mais ce n'est pas le cas. (Je pense que c'est ainsi que votre code ne se cassera pas si vous ajoutez une autre surcharge de cette méthode.)

La réponse de Snowbear contient de bons conseils sur les solutions possibles.