我希望通过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
。)
答案 0 :(得分:0)
一种可能的解决方案似乎是使用ExpressionVisitor
浏览Expression
并查找值为ConstantExpression
的{{1}} MethodInfo
,MethodInfo.DeclaringType
是正确的类......
这似乎适用于.NET≤4和.NET 4.5。