【问题标题】:Func<> getting the parameter infoFunc<> 获取参数信息
【发布时间】:2021-04-17 23:43:27
【问题描述】:

C#中如何获取Func&lt;&gt;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

的过滤器扩展方法中获取 query 的值

【问题讨论】:

  • 您必须使用Expression&lt;Func&lt;T,bool&gt;&gt; 来获取该信息。
  • 好的..我正在尝试,但我不知道从哪里得到它..也许在predicate.Body....Right的某个地方@

标签: c# lambda func


【解决方案1】:

如果要获取参数,则必须传递表达式。通过传递“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

【讨论】:

    【解决方案2】:

    所以不要将您的谓词作为Func&lt;T,bool&gt; 传递,而是传递一个表达式树而不是Expression&lt;Func&lt;T,bool&gt;

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

    【讨论】:

    • 我做到了。var _a = predicate; var _aa = _a.Body as System.Linq.Expressions.BinaryExpression; var _r = _aa.Right; 现在我想获得_r 的值
    • 是的,就是这样......但您需要检查表达式类型,因为它可能不是二进制表达式,可能是方法调用或常量等
    • _r 也将是一个表达式,如果它是一个常量,那么你很可爱,但当然它也可能是一个方法调用,你只需要继续遍历树(通常你会使用访问者这样做)
    【解决方案3】:

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

    您的predicate 设置为Func&lt;T, bool&gt; predicate,因此您可以这样称呼它:

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

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

    (p) =&gt; true 满足Func&lt;T, bool&gt;,因为它将T 作为输入并返回bool 值。

    【讨论】:

    • 我想获取_query 的值,以便检查它是否包含值..
    【解决方案4】:

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

    1. 将 Func 包装在一个表达式中

    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();
       }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      • 1970-01-01
      • 2014-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多