gpt4 book ai didi

c# - 如何记录谓词表达式?

转载 作者:太空狗 更新时间:2023-10-29 17:54:11 29 4
gpt4 key购买 nike

通常我的存储库有用于调试目的的日志语句,允许我查看参数值。最近我走上了创建一个通用存储库的道路,该存储库将谓词表达式作为具有极大灵 active 的参数,但是我想不出一种合适的方法来将条件记录到远程有用的地方。

示例方法:

public int GetCount<K>(Expression<Func<K, bool>> predicate) where K : class
{
Logger.LogDebugMessage(String.Format("Parameters [predicate: {0}]", predicate == null ? string.Empty : predicate.Body.ToString()));

...
}

您可以看到此时我正在使用 Body.ToString(),但结果不是那么可读:

Parameters [predicate: (fa.SomeId == value(NameSpace.SomeClass+<>c__DisplayClass2).SomeId)]

最终我希望看到的是类似于下面的内容:

Parameters [predicate: (fa.SomeId == 1 && fa.Account.Name == "MyName").SomeId)]

从本质上讲,这个日志的值(value)在于能够在某些东西爆炸时知道输入值。有什么办法可以避免强制 API 的用户以字符串形式提供谓词?

最佳答案

Matt Warren 的这篇博文包含用变量名称替换局部变量引用的代码。所以,而不是 predicate: (fa.SomeId == value(NameSpace.SomeClass+<>c__DisplayClass2).SomeId) , 你会得到 predicate: (fa.SomeId == someValue) .

博文:

http://blogs.msdn.com/b/mattwar/archive/2007/08/01/linq-building-an-iqueryable-provider-part-iii.aspx

来源:

public static class Evaluator
{
/// <summary>
/// Performs evaluation & replacement of independent sub-trees
/// </summary>
/// <param name="expression">The root of the expression tree.</param>
/// <param name="fnCanBeEvaluated">A function that decides whether a given expression node can be part of the local function.</param>
/// <returns>A new tree with sub-trees evaluated and replaced.</returns>
public static Expression PartialEval(Expression expression, Func<Expression, bool> fnCanBeEvaluated)
{
return new SubtreeEvaluator(new Nominator(fnCanBeEvaluated).Nominate(expression)).Eval(expression);
}

/// <summary>
/// Performs evaluation & replacement of independent sub-trees
/// </summary>
/// <param name="expression">The root of the expression tree.</param>
/// <returns>A new tree with sub-trees evaluated and replaced.</returns>
public static Expression PartialEval(Expression expression)
{
return PartialEval(expression, Evaluator.CanBeEvaluatedLocally);
}

private static bool CanBeEvaluatedLocally(Expression expression)
{
return expression.NodeType != ExpressionType.Parameter;
}

/// <summary>
/// Evaluates & replaces sub-trees when first candidate is reached (top-down)
/// </summary>
class SubtreeEvaluator : ExpressionVisitor
{
HashSet<Expression> candidates;

internal SubtreeEvaluator(HashSet<Expression> candidates)
{
this.candidates = candidates;
}

internal Expression Eval(Expression exp)
{
return this.Visit(exp);
}

protected override Expression Visit(Expression exp)
{
if (exp == null)
{
return null;
}
if (this.candidates.Contains(exp))
{
return this.Evaluate(exp);
}
return base.Visit(exp);
}

private Expression Evaluate(Expression e)
{
if (e.NodeType == ExpressionType.Constant)
{
return e;
}
LambdaExpression lambda = Expression.Lambda(e);
Delegate fn = lambda.Compile();
return Expression.Constant(fn.DynamicInvoke(null), e.Type);
}
}

/// <summary>
/// Performs bottom-up analysis to determine which nodes can possibly
/// be part of an evaluated sub-tree.
/// </summary>
class Nominator : ExpressionVisitor
{
Func<Expression, bool> fnCanBeEvaluated;
HashSet<Expression> candidates;
bool cannotBeEvaluated;

internal Nominator(Func<Expression, bool> fnCanBeEvaluated)
{
this.fnCanBeEvaluated = fnCanBeEvaluated;
}

internal HashSet<Expression> Nominate(Expression expression)
{
this.candidates = new HashSet<Expression>();
this.Visit(expression);
return this.candidates;
}

protected override Expression Visit(Expression expression)
{
if (expression != null)
{
bool saveCannotBeEvaluated = this.cannotBeEvaluated;
this.cannotBeEvaluated = false;
base.Visit(expression);
if (!this.cannotBeEvaluated)
{
if (this.fnCanBeEvaluated(expression))
{
this.candidates.Add(expression);
}
else
{
this.cannotBeEvaluated = true;
}
}
this.cannotBeEvaluated |= saveCannotBeEvaluated;
}
return expression;
}
}
}

关于c# - 如何记录谓词表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5184253/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com