C# “是叶子,从那里开始。这是对表达式树的一种深度优先搜索
因此,构造只包含这些叶子的linq to objects查询。查看该对象是否包含在结果中。如果不包含,则我们已经找到了它被排除的原因,如果不包含,则进入树(即,使where查询包含更多子句,越靠近原始子句,直到该对象从结果中消失)C# “是叶子,从那里开始。这是对表达式树的一种深度优先搜索,c#,.net,linq,C#,.net,Linq,因此,构造只包含这些叶子的linq to objects查询。查看该对象是否包含在结果中。如果不包含,则我们已经找到了它被排除的原因,如果不包含,则进入树(即,使where查询包含更多子句,越靠近原始子句,直到该对象从结果中消失) 在我看来,困难的部分将是处理原始linq to‘whatever’和链接到对象之间的差异,找出在哪里拆分where claues,处理像连接这样的事情,也可以排除事情,以及处理像SqlMethods.like这样在linq to对象中不起作用的事情。这是一种技巧例如,
在我看来,困难的部分将是处理原始linq to‘whatever’和链接到对象之间的差异,找出在哪里拆分where claues,处理像连接这样的事情,也可以排除事情,以及处理像
SqlMethods.like
这样在linq to对象中不起作用的事情。这是一种技巧例如,从您的示例中,您可以编写一些代码来检查细节,并报告“我搜索了术语x,但返回的对象不在术语x中”
不过,正如其他人建议的那样,我会按照“return me x”的思路来做,然后在代码中,对“x where x.property=y”运行一个查询,并报告不匹配项
接下来,我想问题是,为了生成非匹配列表,您的查询或对象图将变得非常庞大,因为您需要原始对象最初包含(或通过延迟加载扩展以包含)许多排列来确定匹配与否
这与在第一个位置运行查询相反,首先从一个对象开始,然后根据条件进行子选择,然后选择超选择,捕捉非条件
这是一个有趣的问题,我通常会在到达和对象是否被返回的点之前,在客户端或代码方面解决这个问题。但我想完美的解决方案应该是返回单个解决方案,并可能检查它的链接关联。
这些链接不难找到一个通用的“我没有这些”类型的原因,但给出一个“我有这个链接,不是那个链接”的回答会更难
您可能需要提供一个基于某种谓词生成器形式的方法,该方法采用字段和搜索词,如果不匹配,则返回适当的消息
现在有点漫无边际了,但我很想听到这个问题的答案!…对于过滤结果的一次性探索,很难在中击败
Dump
方法。以下是他们的一个示例摘录,展示了它的实际应用:
// Dump returns exactly what it was given, so you can sneakily inject
// a Dump (or even many Dumps) *within* an expression. This is useful
// for monitoring a query as it progresses:
new[] { 11, 5, 17, 7, 13 } .Dump ("Prime numbers")
.Where (n => n > 10) .Dump ("Prime numbers > 10")
.OrderBy (n => n) .Dump ("Prime numbers > 10 sorted")
.Select (n => n * 10) .Dump ("Prime numbers > 10 sorted, times 10!");
这将提供格式良好的结果表:
通过一些有趣的表达式破解,您可以看到集合中每个项目的每个评估阶段的结果。点击断点后检查本地
结果
,以查看评估结果。要实际使用评估结果,只需附加。其中(x=>x.isIncludeInResult)。选择(x=>x.EvaluationTarget)
到生成报告的行
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace ConsoleApplication4
{
[DebuggerDisplay("{Condition} on {EvaluationTarget} is {EvaluationResult}")]
public class ReportItem<T>
{
public string Condition { get; private set; }
public IEnumerable<ReportItem<T>> NestedReports { get; private set; }
public object EvaluationResult { get; private set; }
public T EvaluationTarget { get; private set; }
public ReportItem(Expression condition, IEnumerable<ReportItem<T>> nestedReports, T evaluationTarget, object evaluationResult)
{
Condition = condition.ToString();
NestedReports = nestedReports;
EvaluationTarget = evaluationTarget;
EvaluationResult = evaluationResult;
}
public override string ToString()
{
return string.Format("{0} on {1} is {2}", Condition, EvaluationTarget, EvaluationResult);
}
}
[DebuggerDisplay("Included: {IsIncludedInResult} \n{Summary}")]
public class Report<T>
{
public ReportItem<T> Contents { get; private set; }
public T EvaluationTarget { get; private set; }
public Report(T source, Expression<Func<T, bool>> predicate)
{
EvaluationTarget = source;
IsIncludedInResult = predicate.Compile()(source);
Contents = Recurse(predicate.Parameters.Single(), predicate.Body, source);
}
private object Evaluate(Expression expression, ParameterExpression parameter, T source)
{
var expr = Expression.Lambda(expression, parameter);
var @delegate = expr.Compile();
var value = @delegate.DynamicInvoke(source);
return value;
}
private ReportItem<T> Recurse(ParameterExpression parameter, Expression sourceExpression, T source)
{
var constantExpression = sourceExpression as ConstantExpression;
if(constantExpression != null)
{
return new ReportItem<T>(sourceExpression, null, source, Evaluate(constantExpression, parameter, source));
}
var unaryExpression = sourceExpression as UnaryExpression;
if(unaryExpression != null)
{
var content = Recurse(parameter, unaryExpression.Operand, source);
var result = Evaluate(sourceExpression, parameter, source);
return new ReportItem<T>(sourceExpression, new[]{content}, source, result);
}
var binaryExpression = sourceExpression as BinaryExpression;
if(binaryExpression != null)
{
var left = Recurse(parameter, binaryExpression.Left, source);
var right = Recurse(parameter, binaryExpression.Right, source);
var item = new ReportItem<T>(sourceExpression, new[] {left, right}, source, Evaluate(sourceExpression, parameter, source));
return item;
}
var methodCallExpression = sourceExpression as MethodCallExpression;
if(methodCallExpression != null)
{
var args = methodCallExpression.Arguments.Select(x => Evaluate(x, parameter, source)).ToArray();
var result = methodCallExpression.Method.Invoke(Expression.Lambda(methodCallExpression.Object, parameter).Compile().DynamicInvoke(source), args);
return new ReportItem<T>(sourceExpression, null, source, result);
}
throw new Exception("Unhandled expression type " + sourceExpression.NodeType + " encountered");
}
public bool IsIncludedInResult { get; private set; }
public string Summary
{
get { return Contents.ToString(); }
}
public override string ToString()
{
return Summary;
}
}
public static class PredicateRunner
{
public static IEnumerable<Report<T>> Report<T>(this IEnumerable<T> set, Expression<Func<T, bool>> predicate)
{
return set.Select(x => new Report<T>(x, predicate));
}
}
class MyItem
{
public string Name { get; set; }
public int Value { get; set; }
public override int GetHashCode()
{
return Value % 2;
}
public override string ToString()
{
return string.Format("Name: \"{0}\" Value: {1}", Name, Value);
}
}
class Program
{
static void Main()
{
var items = new MyItem[3];
items[0] = new MyItem
{
Name = "Hello",
Value = 1
};
items[1] = new MyItem
{
Name = "Hello There",
Value = 2
};
items[2] = new MyItem
{
Name = "There",
Value = 3
};
var result = items.Report(x => !x.Name.Contains("Hello") && x.GetHashCode() == 1).ToList();
Debugger.Break();
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统诊断;
使用System.Linq;
使用System.Linq.Expressions;
命名空间控制台应用程序4
{
[DebuggerDisplay({EvaluationTarget}上的{Condition}是{EvaluationResult}”)]
公共类报告项
{
公共字符串条件{get;private set;}
公共IEnumerable嵌套报表{get;private set;}
公共对象求值结果{get;private set;}
公共T评估目标{get;私有集;}
公共报表项(表达式条件、IEnumerable嵌套报表、T evaluationTarget、对象evaluationResult)
{
Condition=Condition.ToString();
NestedReports=NestedReports;
EvaluationTarget=EvaluationTarget;
EvaluationResult=EvaluationResult;
}
公共重写字符串ToString()
{
返回string.Format(“{1}上的{0}为{2}”,条件、EvaluationTarget、EvaluationResult);
}
}
[调试程序显示(“包括:{IsIncludedInResult}\n{Summary}”)]
公开课报告
{
公共报表项内容{get;private set;}
公共T评估目标{get;私有集;}
公共报表(T源、表达式谓词)
{
评估目标=来源;
IsIncludedInResult=predicate.Compile()(源代码);
Contents=Recurse(predicate.Parameters.Single(),predicate.Body,source);
}
私有对象求值(表达式表达式、参数表达式参数、T源)
{
var expr=Expression.Lambda(表达式,参数);
var@delegate=expr.Compile();
var值=@delegate.DynamicInvoke(源);
返回值;
}
私有ReportItem递归(ParameterExpression参数、Expression sourceExpression、T source)
{
var constantExpression=源表达式为constantExpression;
if(constantExpression!=null)
{
返回新的ReportItem(sourceExpression,null,source,Evaluate(constantExpression,parameter,source));
}
var unaryExpression=sourceExpression作为unaryExpression;
if(一元表达式!=null)
{
var content=Recurse(参数、一元表达式、操作数、源);
var结果=评估(源表达式、参数、源);
返回新的ReportItem(sourceExpression,new[]{content},source,result);
}
var binaryExpression=sourceExpression作为binaryExpression;
if(二进制表达式!=null)
{
var left=Recurse(参数,binaryExpression.left,source);
var right=Recurse(参数,binaryExpression.right,source);
变量项=新
where obj.foo == true && obj.bar == "yes"
// Dump returns exactly what it was given, so you can sneakily inject
// a Dump (or even many Dumps) *within* an expression. This is useful
// for monitoring a query as it progresses:
new[] { 11, 5, 17, 7, 13 } .Dump ("Prime numbers")
.Where (n => n > 10) .Dump ("Prime numbers > 10")
.OrderBy (n => n) .Dump ("Prime numbers > 10 sorted")
.Select (n => n * 10) .Dump ("Prime numbers > 10 sorted, times 10!");
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace ConsoleApplication4
{
[DebuggerDisplay("{Condition} on {EvaluationTarget} is {EvaluationResult}")]
public class ReportItem<T>
{
public string Condition { get; private set; }
public IEnumerable<ReportItem<T>> NestedReports { get; private set; }
public object EvaluationResult { get; private set; }
public T EvaluationTarget { get; private set; }
public ReportItem(Expression condition, IEnumerable<ReportItem<T>> nestedReports, T evaluationTarget, object evaluationResult)
{
Condition = condition.ToString();
NestedReports = nestedReports;
EvaluationTarget = evaluationTarget;
EvaluationResult = evaluationResult;
}
public override string ToString()
{
return string.Format("{0} on {1} is {2}", Condition, EvaluationTarget, EvaluationResult);
}
}
[DebuggerDisplay("Included: {IsIncludedInResult} \n{Summary}")]
public class Report<T>
{
public ReportItem<T> Contents { get; private set; }
public T EvaluationTarget { get; private set; }
public Report(T source, Expression<Func<T, bool>> predicate)
{
EvaluationTarget = source;
IsIncludedInResult = predicate.Compile()(source);
Contents = Recurse(predicate.Parameters.Single(), predicate.Body, source);
}
private object Evaluate(Expression expression, ParameterExpression parameter, T source)
{
var expr = Expression.Lambda(expression, parameter);
var @delegate = expr.Compile();
var value = @delegate.DynamicInvoke(source);
return value;
}
private ReportItem<T> Recurse(ParameterExpression parameter, Expression sourceExpression, T source)
{
var constantExpression = sourceExpression as ConstantExpression;
if(constantExpression != null)
{
return new ReportItem<T>(sourceExpression, null, source, Evaluate(constantExpression, parameter, source));
}
var unaryExpression = sourceExpression as UnaryExpression;
if(unaryExpression != null)
{
var content = Recurse(parameter, unaryExpression.Operand, source);
var result = Evaluate(sourceExpression, parameter, source);
return new ReportItem<T>(sourceExpression, new[]{content}, source, result);
}
var binaryExpression = sourceExpression as BinaryExpression;
if(binaryExpression != null)
{
var left = Recurse(parameter, binaryExpression.Left, source);
var right = Recurse(parameter, binaryExpression.Right, source);
var item = new ReportItem<T>(sourceExpression, new[] {left, right}, source, Evaluate(sourceExpression, parameter, source));
return item;
}
var methodCallExpression = sourceExpression as MethodCallExpression;
if(methodCallExpression != null)
{
var args = methodCallExpression.Arguments.Select(x => Evaluate(x, parameter, source)).ToArray();
var result = methodCallExpression.Method.Invoke(Expression.Lambda(methodCallExpression.Object, parameter).Compile().DynamicInvoke(source), args);
return new ReportItem<T>(sourceExpression, null, source, result);
}
throw new Exception("Unhandled expression type " + sourceExpression.NodeType + " encountered");
}
public bool IsIncludedInResult { get; private set; }
public string Summary
{
get { return Contents.ToString(); }
}
public override string ToString()
{
return Summary;
}
}
public static class PredicateRunner
{
public static IEnumerable<Report<T>> Report<T>(this IEnumerable<T> set, Expression<Func<T, bool>> predicate)
{
return set.Select(x => new Report<T>(x, predicate));
}
}
class MyItem
{
public string Name { get; set; }
public int Value { get; set; }
public override int GetHashCode()
{
return Value % 2;
}
public override string ToString()
{
return string.Format("Name: \"{0}\" Value: {1}", Name, Value);
}
}
class Program
{
static void Main()
{
var items = new MyItem[3];
items[0] = new MyItem
{
Name = "Hello",
Value = 1
};
items[1] = new MyItem
{
Name = "Hello There",
Value = 2
};
items[2] = new MyItem
{
Name = "There",
Value = 3
};
var result = items.Report(x => !x.Name.Contains("Hello") && x.GetHashCode() == 1).ToList();
Debugger.Break();
}
}
}