通过Linq表达式指定MethodInfo的面向未来的方法

时间:2014-05-28 10:28:03

标签: c# linq reflection

我希望通过Linq表达式指定方法的面向未来的方式。

我正在设计一个允许用户指定方法的API。例如,客户端代码可能如下所示:ApiClass<ClientClass>.DoSomething(c => c.ClientMethod)

我的API是强类型的。例如,

public void DoSomething(Expression<Func<TClientClass, Func<TParams, TResult>>> method){ ... }

我的问题:如何正确解析Expression树以获取客户端指定的MethodInfo?

我一直在使用下面的代码,但似乎.NET 4.5的4.5版通过生成稍微不同的表达式树来打破它。我显然更喜欢有一些适用于所有未来版本的C#/ .NET

的东西

现有代码(类似于回答SO Extract method name from expression tree?):

private static MethodInfo GetMethodInfo(Expression method)
{
    var lambda = method as LambdaExpression;
    if (lambda == null) throw new ArgumentException("Argument is not a lambda expression (c => c.Thing)");
    var convert = lambda.Body;
    var body = (convert.NodeType == ExpressionType.Convert)
        ? ((UnaryExpression)convert).Operand as MethodCallExpression
        : convert as MethodCallExpression;
    if (body == null) throw new ArgumentException("Argument not in correct form (c => c.Thing)");
    var methodInfoValue = body
        .Arguments.OfType<ConstantExpression>()
        .Where(exp => exp.Type == typeof(MethodInfo))
        .Select(exp => (MethodInfo)exp.Value)
        .FirstOrDefault();
    if (methodInfoValue == null) throw new ArgumentException("Cannot find method name in expression.");
    return methodInfoValue;
}

(此代码在.NET 4.5.1上失败:最终为空methodInfoValue。)

1 个答案:

答案 0 :(得分:0)

一种可能的解决方案似乎是使用ExpressionVisitor浏览Expression并查找值为ConstantExpression的{​​{1}} MethodInfoMethodInfo.DeclaringType是正确的类......

这似乎适用于.NET≤4和.NET 4.5。