在LINQ to Objects中,无论如何都要确定哪些实体/对象在每个过滤器上合格/不合格?
例如)假设我有一个名为“产品”(Id,名称)的实体,如果我将100个产品输入Linq查询,其中有5个“where”条件并获得20个产品作为输出。
有没有办法确定哪个产品被过滤了哪个条件?
答案 0 :(得分:2)
这可能是一般化的,但你可以做到这一点。我只是没有看到它的用例。
使用ToLookup()
对查询进行分区。 "取消资格"项目将归入false
群组,您可以继续使用true
群组进行查询。
如,
var numbers = Enumerable.Range(0, 100);
var p1 = numbers.ToLookup(n1 => n1 < 50);
// p1[false] -> [ 50, 51, 52, ... ]
var p2 = p1[true].ToLookup(n2 => n2 % 2 == 0);
// p2[false] -> [ 1, 3, 5, 7, ... ]
var p3 = p2[true]... // and so on
答案 1 :(得分:0)
虽然到目前为止每个人都向您展示了如何做出明显的事情,即将您的数据分组为符合一个条件的块,但是没有人解决您实际要求的问题
确定哪个产品已过滤哪个条件
棘手的问题是如何记录where条件?
执行此操作似乎微不足道,但您将失败,因为您将无法获取所使用的Func
对象的字符串表示形式。它是一个委托,即编译代码,您必须在运行时对其进行反向工程以获取源代码。这本身就足够了,但是如果编译器选择优化你失去的代码。
只有当您愿意创建自己的扩展方法(使用表达式而不是Func
s)时,您才能记录where条件,因为表达式由在运行时很容易被“ToString-ed”的标记组成。
例如:
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();
}
}
现在你真的拦截了过滤器。但是你不知道在代码中应用过滤器的位置。如果你还想记录堆栈帧,性能可能会成为一个问题(反思!),因为每次编译表达式都已经面临压力。然后,日志记录应该是涉及线程安全日志记录队列的异步操作。