Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “是叶子,从那里开始。这是对表达式树的一种深度优先搜索_C#_.net_Linq - Fatal编程技术网

C# “是叶子,从那里开始。这是对表达式树的一种深度优先搜索

C# “是叶子,从那里开始。这是对表达式树的一种深度优先搜索,c#,.net,linq,C#,.net,Linq,因此,构造只包含这些叶子的linq to objects查询。查看该对象是否包含在结果中。如果不包含,则我们已经找到了它被排除的原因,如果不包含,则进入树(即,使where查询包含更多子句,越靠近原始子句,直到该对象从结果中消失) 在我看来,困难的部分将是处理原始linq to‘whatever’和链接到对象之间的差异,找出在哪里拆分where claues,处理像连接这样的事情,也可以排除事情,以及处理像SqlMethods.like这样在linq to对象中不起作用的事情。这是一种技巧例如,

因此,构造只包含这些叶子的linq to objects查询。查看该对象是否包含在结果中。如果不包含,则我们已经找到了它被排除的原因,如果不包含,则进入树(即,使where查询包含更多子句,越靠近原始子句,直到该对象从结果中消失)


在我看来,困难的部分将是处理原始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();
        }
    }
}