C# 从表达式调用方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/439172/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:26:23  来源:igfitidea点击:

Calling a Method from an Expression

c#lambda

提问by blu

What types and arguments does the method, "Any" when using Expression.Call take?

使用 Expression.Call 时,方法“Any”采用哪些类型和参数?

I have an inner and an outer Expression that I would like to use with Any. The expressions are built programatically.

我有一个内部表达式和一个外部表达式,我想与 Any 一起使用。表达式以编程方式构建。

Inner (this works):

内部(这有效):

ParameterExpression tankParameter = Expression.Parameter(typeof(Tank), "t");
Expression tankExpression = Expression.Equal(
    Expression.Property(tankParameter, "Gun"),
    Expression.Constant("Really Big"));

Expression<Func<Tank, bool>> tankFunction = 
    Expression.Lambda<Func<Tank, bool>>(tankExpression, tankParameter); 

Outer (looks correct):

外部(看起来正确):

ParameterExpression vehicleParameter = Expression.Parameter(typeof(Vehicle), "v");

Expression vehicleExpression = Expression.Lambda(
    Expression.Property(
        vehicleParameter, 
        typeof(Vehicle).GetProperty("Tank")), 
    vehicleParameter);

This gives me 2 expressions:

这给了我两个表达:

v => v.Tank
t => t.Gun == "Really Big";

And I am looking for is:

我正在寻找的是:

v => v.Tank.Any(t => t.Gun == "Really Big");

I am attempting to use the Expression.Call method to use, "Any". 1. Is that the right way to do it? 2. The following throws an exception, "No method 'Any' on type 'System.Linq.Queryable' is compatible with the supplied arguments."

我正在尝试使用 Expression.Call 方法来使用“任何”。1. 这是正确的做法吗?2. 以下内容引发异常,“类型 'System.Linq.Queryable' 上的任何方法 'Any' 均与提供的参数不兼容。”

Here is how I am calling Any:

这是我调用 Any 的方式:

Expression any = Expression.Call(
    typeof(Queryable),
    "Any",
    new Type[] { tankFunction.Body.Type }, // this should match the delegate...
    tankFunction);

How is the Any called chained from vehicleExpression to tankFunction?

Any 调用如何从 VehicleExpression 链接到 tankFunction?

采纳答案by Marc Gravell

I had a similar problem when trying to get string.Containsto work; I just used the GetMethod/MethodInfoapproach instead; however - it is complicated because it is a generic method...

我在string.Contains上班时遇到了类似的问题;我只是使用了GetMethod/MethodInfo方法;但是 - 它很复杂,因为它是一种通用方法......

This should be the right MethodInfo- but it is hard to give a full (runnable) answer without a bit more clarity on Tankand Vehicle:

这应该是正确的MethodInfo- 但是如果没有更清楚地说明Tank和,很难给出完整的(可运行的)答案Vehicle

   MethodInfo method = typeof(Queryable).GetMethods()
        .Where(m => m.Name == "Any"
            && m.GetParameters().Length == 2)
        .Single().MakeGenericMethod(typeof(Tank));

Note that extension methods work backwards - so you actually want to call methodwith the two args (the source and the predicate).

请注意,扩展方法向后工作 - 因此您实际上想要method使用两个参数(源和谓词)进行调用。

Something like:

就像是:

   MethodInfo method = typeof(Queryable).GetMethods()
        .Where(m => m.Name == "Any" && m.GetParameters().Length == 2)
        .Single().MakeGenericMethod(typeof(Tank));

    ParameterExpression vehicleParameter = Expression.Parameter(
        typeof(Vehicle), "v");
    var vehicleFunc = Expression.Lambda<Func<Vehicle, bool>>(
        Expression.Call(
            method,
            Expression.Property(
                vehicleParameter,
                typeof(Vehicle).GetProperty("Tank")),
            tankFunction), vehicleParameter);

If in doubt, use reflector (and fiddle it a bit ;-p) - for example, I wrote a test method as per your spec:

如果有疑问,请使用反射器(并稍微调整一下;-p)-例如,我根据您的规范编写了一个测试方法:

Expression<Func<Vehicle, bool>> func = v => v.Tank.Any(
    t => t.Gun == "Really Big");

And decompiled it and toyed with it...

并反编译它并玩弄它......