【发布时间】:2016-01-05 06:22:49
【问题描述】:
我正在表达式树中做一些工作,这是一种规则引擎。
当您在表达式树上调用 ToString() 时,您会得到一些可爱的诊断文本:
((Param_0.Customer.LastName == "Doe")
AndAlso ((Param_0.Customer.FirstName == "John")
Or (Param_0.Customer.FirstName == "Jane")))
我编写了这段代码,试图用一些日志记录功能包装表达式:
public Expression WithLog(Expression exp)
{
return Expression.Block(Expression.Call(
typeof (Debug).GetMethod("Print",
new Type [] { typeof(string) }),
new [] { Expression.Call(Expression.Constant(exp),
exp.GetType().GetMethod("ToString")) } ), exp);
}
这应该允许我在表达式树中的不同位置插入日志记录,并在表达式树执行时获得中间 ToString() 结果。
我还没有完全弄清楚的是如何获取每个子表达式的计算结果并将其包含在日志输出中。理想情况下,出于诊断和审计目的,我希望看到类似这样的输出:
Executing Rule: (Param_0.Customer.LastName == "Doe") --> true
Executing Rule: (Param_0.Customer.FirstName == "John") --> true
Executing Rule: (Param_0.Customer.FirstName == "Jane") --> false
Executing Rule: (Param_0.Customer.FirstName == "John") Or (Param_0.Customer.FirstName == "Jane")) --> true
Executing Rule: (Param_0.Customer.LastName == "Doe") AndAlso ((Param_0.Customer.FirstName == "John") Or (Param_0.Customer.FirstName == "Jane")) --> true
我怀疑我需要使用 ExpressionVisitor 遍历树并向每个节点添加一些代码,或者遍历树并单独编译和执行每个子树,但我还没有完全弄清楚如何使这项工作。
有什么建议吗?
【问题讨论】:
-
您需要使用表达式访问者。您需要编译作为 lambda 表达式的节点。然后,您可以将编译后的 lambda 作为委托执行。如果没记错的话,每个 lambda 节点上都有一个 compile 方法,它会返回一个委托。您可以执行委托以获得结果。
标签: c# logging expression-trees instrumentation