Lambda表达式<T,Func >和MethodInfo

在将项目从VS2010迁移到VS2012时,我遇到了以下问题。 该项目使用了很多reflection,为了从接口获取MethodInfo,放置了以下代码:

Expression<Func<ITest, Func>> expression = scv => scv.Get; UnaryExpression unaryExpression = expression.Body as UnaryExpression; MethodCallExpression methodCallExpression = unaryExpression.Operand as MethodCallExpression; ConstantExpression constantExpression = methodCallExpression.Arguments[2] as ConstantExpression; MethodInfo myMethod = constantExpression.Value as MethodInfo; 

使用VS2010编译时效果很好,但是如果使用针对.Net 4.0的VS2012编译代码,则methodCallExpression.Arguments.Count()为2。

反编译后,我注意到编译器为同一个表达式生成了不同的代码。

这是一个设计问题,因为设计不应该像methodCallExpression.Arguments [2]中的数字2那样继续传递“幻数”。 我尝试使用以下方法找到解决方案:

 MethodCallExpression outermostExpression = expression .Body as MethodCallExpression; MethodInfo myMethod = outermostExpression.Method; 

但是outermostExpression为null。

最后,我让它改变了表达式如下:

 Expression<Func> expression = scv => scv.Get(default(ServiceRequest)); MethodCallExpression outermostExpression = expression.Body as MethodCallExpression; Assert.AreEqual("Get", outermostExpression.Method.Name); 

它并不理想,但它适用于VS2010和VS2012。

有没有办法从如下表达式中找到MethodInfo:

 Expression<Func> expression = scv => scv.Get(default(ServiceRequest)); MethodInfo methodInfo = GetInnerMethodInfo( expression ); Assert.AreEqual("Get", methodInfo.Name); 

我不确定为什么表达式编译的方式有所不同。 但是,如果您在常量委托中查找方法的方法信息,则可以使用ITest实现编译表达式以获取委托MethodInfo 。 例如:

 Expression>> expression = scv => new Func(scv.Get); Func ret = expression.Compile()(new Test()); MethodInfo methodInfo = ret.Method; 

..where Test是一些类并实现ITest 。 哪个适用于2012年和2010年。

我不确定如何在不首先编译它的情况下从2012年的表达式中获取方法信息…

更新:

如果编译表达式不是一个选项,则看起来编译器正在生成不同的表达式并将MethodInfo放在C#5编译器的MethodCallExpression.Object属性中。 您可以检查该属性是否为null并将其值用于MethodInfo ,或继续获取Arguments集合中的元素。 例如:

 Expression>> expression = scv => new Func(scv.Get); UnaryExpression unaryExpression = expression.Body as UnaryExpression; MethodCallExpression methodCallExpression = unaryExpression.Operand as MethodCallExpression; ConstantExpression constantExpression = methodCallExpression.Object as ConstantExpression; MethodInfo methodInfo; if (constantExpression != null) { methodInfo = constantExpression.Value as MethodInfo; } else { constantExpression = methodCallExpression.Arguments .Single(a => a.Type == typeof(MethodInfo) && a.NodeType == ExpressionType.Constant) as ConstantExpression; methodInfo = constantExpression.Value as MethodInfo; } 

我正在使用LINQ查询来获取Arguments集合中的元素,如果您更喜欢硬编码索引,则可以使用它。 还需要更完整的错误检查。