C# Lambda表达式<;T、 Func<;锡,托特>&燃气轮机;和MethodInfo

C# Lambda表达式<;T、 Func<;锡,托特>&燃气轮机;和MethodInfo,c#,reflection,lambda,visual-studio-2012,methodinfo,C#,Reflection,Lambda,Visual Studio 2012,Methodinfo,将项目从VS2010迁移到VS2012时,我遇到了以下问题。该项目经常使用反射,为了从接口获取MethodInfo,放置了以下代码: Expression<Func<ITest, Func<ServiceRequest, ServiceResponse>>> expression = scv => scv.Get; UnaryExpression unaryExpression = expression.Body as UnaryExpression;

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

Expression<Func<ITest, Func<ServiceRequest, ServiceResponse>>> 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;
但是最外层的表达式是空的

最后,我对表达式进行了如下更改:

Expression<Func<ITest, ServiceResponse>> expression = scv => scv.Get(default(ServiceRequest));
MethodCallExpression outermostExpression = expression.Body as MethodCallExpression;
Assert.AreEqual("Get", outermostExpression.Method.Name);
Expression=scv=>scv.Get(默认值(ServiceRequest));
MethodCallExpression OutermosteExpression=表达式。主体为MethodCallExpression;
AreEqual(“Get”,最外层的表达式.Method.Name);
这并不理想,但它可以在VS2010和VS2012上运行

有没有一种方法可以从以下表达式中找到MethodInfo:

MethodCallExpression outermostExpression = expression .Body as MethodCallExpression;
MethodInfo myMethod = outermostExpression.Method;
Expression<Func<ITest, ServiceResponse>> expression = scv => scv.Get(default(ServiceRequest));
MethodInfo methodInfo = GetInnerMethodInfo( expression );
Assert.AreEqual("Get", methodInfo.Name);
Expression=scv=>scv.Get(默认值(ServiceRequest));
MethodInfo MethodInfo=GetInnerMethodInfo(表达式);
arenequal(“Get”,methodInfo.Name);

我不知道为什么表达式的编译方式会有差异。但是,如果要在常量委托中查找方法的方法信息,可以使用
ITest
实现编译表达式,以获取委托
MethodInfo
。例如:

Expression<Func<ITest, Func<ServiceRequest, ServiceResponse>>> expression = scv => new Func<ServiceRequest, ServiceResponse>(scv.Get);
Func<ServiceRequest, ServiceResponse> ret = expression.Compile()(new Test());
MethodInfo methodInfo = ret.Method;
Expression<Func<ITest, Func<ServiceRequest, ServiceResponse>>> expression = 
    scv => new Func<ServiceRequest, ServiceResponse>(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
集合中的元素,如果您更喜欢硬编码索引,您可能会使用它。还有必要进行更全面的错误检查。

Peter,非常感谢您的回答。这将解决“幻数”的问题,但真正的问题是MethodInfo不在集合中。以下测试失败。ConstantExpression ConstantExpression=methodCallExpression.Arguments.FirstOrDefault(a=>a.Type==typeof(MethodInfo)&&a.NodeType==ExpressionType.Constant)作为ConstantExpression;Assert.IsNotNull(constantExpression);更新了我的答案和一些进一步的发现。非常感谢。编译表达式不是一个选项,我更喜欢LINQ查询而不是索引方法。事件当我瞄准.Net 4.0时,编译器以不同的方式“翻译”lambda表达式,将MethodInfo放在MethodCallExpression.Object中,而不是MethodCallExpression.Arguments中。它看起来像是从.Net 4.0到.Net 4.5编译器的突破性变化。非常感谢你的帮助。