如何拦截Linq滤波器

如何拦截Linq滤波器,linq,filter,pipe,Linq,Filter,Pipe,在LINQ to Objects中,是否可以确定在每个过滤器中合格/不合格的实体/对象 例如,假设我有一个名为“Product”(Id,name)的实体,如果我在一个Linq查询中输入100个产品,该查询有5个“where”条件,并得到20个产品作为输出 有没有办法确定哪种产品在哪种情况下被过滤?这可能是通用的,但你可以这样做。我只是看不到它的用例 使用ToLookup()对查询进行分区。“不合格”项将集中在false组下,您可以使用true组继续查询 e、 g var numbers=Enum

在LINQ to Objects中,是否可以确定在每个过滤器中合格/不合格的实体/对象

例如,假设我有一个名为“Product”(Id,name)的实体,如果我在一个Linq查询中输入100个产品,该查询有5个“where”条件,并得到20个产品作为输出


有没有办法确定哪种产品在哪种情况下被过滤?

这可能是通用的,但你可以这样做。我只是看不到它的用例

使用
ToLookup()
对查询进行分区。“不合格”项将集中在
false
组下,您可以使用
true
组继续查询

e、 g

var numbers=Enumerable.Range(0,100);
var p1=数字。ToLookup(n1=>n1<50);
//p1[false]->[50,51,52,…]
变量p2=p1[true].ToLookup(n2=>n2%2==0);
//p2[false]->[1,3,5,7,…]
var p3=p2[true]…//依此类推

到目前为止,每个人都向您展示了如何做显而易见的事情,即将数据分组为符合一个条件的数据块,但没有人回答您实际提出的问题

确定在哪种条件下过滤了哪种产品

难题是如何记录where条件?

这样做可能看起来很简单,但您将失败,因为您将无法获取所使用的
Func
对象的字符串表示形式。它是一个委托,即编译代码,您必须在运行时对其进行反向工程以获取源代码。这本身就很难,但如果编译器选择对丢失的代码进行加密

只有当您愿意创建使用表达式而不是
Func
s的自己的扩展方法时,您才能够记录where条件,因为表达式包含可以在运行时轻松“ToString”的标记

例如:

public static IEnumerable<T> WhereEx<T>(this IEnumerable<T> sequence, Expression<Func<T, bool>> condition)
{
    var logString = condition.Body.ToString();
    foreach (T item in sequence.Where(condition.Compile()))
    {
        yield return item;
        // logging hook here, this one simply dumps in Linqpad.
        string.Format("Item '{0}' meets '{1}'", item, logString).Dump();
    }
}
公共静态IEnumerable WhereEx(此IEnumerable序列、表达式条件)
{
var logString=condition.Body.ToString();
foreach(序列中的T项。其中(condition.Compile()))
{
收益回报项目;
//这里是日志钩子,这个钩子只是转储到Linqpad中。
Format(“项{0}与{1}”相遇,项,logString).Dump();
}
}

现在您确实正在拦截筛选器。但是您不知道筛选器在代码中的何处应用。如果您还想记录堆栈帧,则性能可能会成为一个问题(反射!),因为每次编译表达式都会给它带来压力。那么日志记录应该是一个异步操作,包含一个线程安全的日志记录队列。

这就是您要找的吗?(另外,看起来您对您的问题发表了评论,而不是对我的答案发表了评论:p)谢谢你的回复。我想在不同的地方记录这些信息,而不是在多个地方进行更改。是否有任何一种通用的方法将其保存在一个地方或以最小的更改量保存呢?我可以想出几种方法使语言符合你的意愿:你可以实现你自己的
where
方法使用这种方法进行日志记录,但我不会,因为这对我来说太难了。如果一个实体不符合第一个条件,它可能符合接下来的四个条件,购买它永远不会通过。你如何处理?如果你想记录数据,那么实现一个标准的日志记录程序,它将IEnumerable作为输入和日志,不管你需要什么o相关位置。事实上,扩展方法将是一个好主意
public static IEnumerable<T> WhereEx<T>(this IEnumerable<T> sequence, Expression<Func<T, bool>> condition)
{
    var logString = condition.Body.ToString();
    foreach (T item in sequence.Where(condition.Compile()))
    {
        yield return item;
        // logging hook here, this one simply dumps in Linqpad.
        string.Format("Item '{0}' meets '{1}'", item, logString).Dump();
    }
}