用记录器包装表达式树

时间:2015-12-01 00:30:59

标签: c# expression-trees

我正在表达树中做一些工作。当您在表达式树上调用ToString()时,您会得到一些可疑的诊断文本(这里是一个示例):

 ((Param_0.Customer.LastName == "Doe") 
     AndAlso ((Param_0.Customer.FirstName == "John") 
     Or (Param_0.Customer.FirstName == "Jane")))

所以我编写了这段代码,试图用一些日志记录功能包装Expression:

public Expression WithLog(Expression exp)
{
    return Expression.Block(exp, Expression.Call(
        typeof (Debug).GetMethod("Print",
            new Type [] { typeof(string) }),
        new [] { exp } ));
}

我期望方法调用推断出ToString()用法,但我想这是一个编译时功能。当我执行此操作时,我收到错误:

  

'System.Boolean'类型的表达式不能用于方法'Void Print(System.String)

的'System.String'类型的参数

足够公平。但是当我改变它时:

public Expression WithLog(Expression exp)
{
    return Expression.Block(exp, Expression.Call(
        typeof (Debug).GetMethod("Print",
            new Type [] { typeof(string) }),
        new [] { exp.ToString() } ));
}

它无法编译。为什么?我需要做些什么才能解决这个问题?

1 个答案:

答案 0 :(得分:2)

根据我的评论,它期待Expression[],但您已通过string[]。您可以执行此操作,这将立即在ToString()上运行exp

public Expression WithLog(Expression exp)
{
    return Expression.Block(Expression.Call(
        typeof (Debug).GetMethod("Print",
            new Type [] { typeof(string) }),
        new [] { Expression.Constant(exp.ToString()) } ), exp);
}

哪个收益率:

Print("c => ((c.LastName == "Doe") AndAlso ((c.FirstName == "John") OrElse (c.LastName == "Jane")))")

或者,您可以将Expression.Constant(exp.ToString())更改为ToStringexp的调用,以便在调用表达式时执行ToString

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);
}

给出了:

Print(c => ((c.LastName == "Doe") AndAlso ((c.FirstName == "John") OrElse (c.LastName == "Jane"))).ToString())