8

如何Func<>在 C# 中获取 Lambda的传递参数的值

IEnumerable<AccountSummary> _data = await accountRepo.GetAsync();
string _query = "1011";
Accounts = _data.Filter(p => p.AccountNumber == _query);

这是我的扩展方法

public static ObservableCollection<T> Filter<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
{
        string _target = predicate.Target.ToString();
        // i want to get the value of query here.. , i expect "1011"

        throw new NotImplementedException();
}

我想在分配给_target的过滤器扩展方法中获取查询的值

4

4 回答 4

12

如果要获取参数,则必须传递表达式。通过传递“Func”,您将传递已编译的 lambda,因此您无法再访问表达式树。

public static class FilterStatic
{
    // passing expression, accessing value
    public static IEnumerable<T> Filter<T>(this IEnumerable<T> collection, Expression<Func<T, bool>> predicate)
    {
        var binExpr = predicate.Body as BinaryExpression;
        var value = binExpr.Right;

        var func = predicate.Compile();
        return collection.Where(func);
    }

    // passing Func
    public static IEnumerable<T> Filter2<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
    {
        return collection.Where(predicate);
    }
}

测试方法

var accountList = new List<Account>
{
    new Account { Name = "Acc1" },
    new Account { Name = "Acc2" },
    new Account { Name = "Acc3" },
};
var result = accountList.Filter(p => p.Name == "Acc2");  // passing expression
var result2 = accountList.Filter2(p => p.Name == "Acc2");  // passing function
于 2013-07-17T07:32:00.957 回答
1

因此,不要将您的谓词作为Func<T,bool>传递,而是传递一个表达式树Expression<Func<T,bool>

然后您可以检查它是什么类型的表达式并获取它的组成部分,它不会影响方法的调用方式,您仍然可以向它传递一个 lambda。

于 2013-07-17T06:38:10.703 回答
0

我真的不认为你能做到这一点。检查以下情况:

predicate的设置为Func<T, bool> predicate,因此您可以这样称呼它:

Accounts = _data.Filter(p => true);

你想从这样的电话中得到什么?

(p) => true满足Func<T, bool>,因为它T作为输入并返回bool值。

于 2013-07-17T06:31:35.220 回答
0

我受到弗里德的回答的启发,并找到了另一种解决此问题的方法:

  1. 将 Func<T, bool> 包裹在一个表达式中

  2. 将 Expression.Right 转换为 Lambda 函数 Func,它将返回表达式的 RHS 值。

     public static void Filter<T>(this IEnumerable<T> collection, Expression<Func<T, bool>> predicate)
     {
        int value = Expression.Lambda<Func<int>>(predicate.Right).Compile().Invoke();
     }
    
于 2021-04-17T15:34:24.177 回答