2015-12-01 3 views
1

Я выполняю некоторые работы в деревьях выражений. При вызове ToString() на дереве Expression, вы получите прекрасные немногих диагностического текст (здесь выборка):Обертка дерева выражений с помощью регистратора

((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(exp, Expression.Call(
     typeof (Debug).GetMethod("Print", 
      new Type [] { typeof(string) }), 
     new [] { exp })); 
} 

Я наполовину ожидал, что вызов метода вывести использование ToString(), но я предполагаю, что это функция времени компиляции. Когда я это сделаю, я получаю сообщение об ошибке:

Expression of type 'System.Boolean' cannot be used for parameter of type 'System.String' of method 'Void Print(System.String)

Справедливо. Но когда я меняю это на это:

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

Не компилируется. Зачем? И что мне нужно сделать, чтобы исправить это?

+0

Это не компилируется, потому что он ожидает массив 'Expression's, но вы даете ему массив строк. Вам нужно будет изменить его на выражение, которое вызывает 'ToString' на' Expression.Constant (exp) ' – Rob

ответ

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()) быть призывание ToString на exp, так что 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()) 
+0

По-видимому, некоторые из моих предположений о том, как это работает, были недопустимыми, потому что теперь я получаю ошибку' Бинарный оператор Or не определен для типов «System.Void» и «System.Void» ... Но я собираюсь отметить это законченное в любом случае, так как он решил проблему под рукой. Спасибо. –

+0

@RobertHarvey Рад помочь. Что касается вашей другой ошибки, могу ли я предположить, что вы делаете что-то вроде выражения Expression.OrElse (WithLog (...), ...) '? Если это * - это случай, вам нужно будет изменить блок в методе 'WithLog', чтобы вернуть исходное выражение. Как бы то ни было, он компилируется в нечто вроде '(e) => Print (exp) || e.LastName = "Doe" ' – Rob

+0

Больше похоже на' WithLog (Expression.OrElse (blah)) '. Но да, что-то в этом роде. И ты прав; Я думаю, мне нужно вернуть оригинальное выражение, а не новое. Я довольно новичок в Деревьях выражений. –

Смежные вопросы