I'm doing some work in Expression Trees. When you call ToString() on an Expression Tree, you get a lovely bit of diagnostic text (here is a sampling):
((Param_0.Customer.LastName == "Doe")
AndAlso ((Param_0.Customer.FirstName == "John")
Or (Param_0.Customer.FirstName == "Jane")))
So I wrote this bit of code, in an attempt to wrap the Expression with some logging capability:
public Expression WithLog(Expression exp)
{
return Expression.Block(exp, Expression.Call(
typeof (Debug).GetMethod("Print",
new Type [] { typeof(string) }),
new [] { exp } ));
}
I half-expected the method call to infer the ToString() usage, but I suppose that's a compile-time feature. When I execute this, I get the error:
Expression of type 'System.Boolean' cannot be used for parameter of type 'System.String' of method 'Void Print(System.String)
Fair enough. But when I change it to this:
public Expression WithLog(Expression exp)
{
return Expression.Block(exp, Expression.Call(
typeof (Debug).GetMethod("Print",
new Type [] { typeof(string) }),
new [] { exp.ToString() } ));
}
It doesn't compile. Why? And what do I need to do to fix this?
As per my comment, it's expecting Expression[]
, but you've passed it string[]
. You can do this, which will immediately run ToString()
on 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);
}
Which yields:
Print("c => ((c.LastName == "Doe") AndAlso ((c.FirstName == "John") OrElse (c.LastName == "Jane")))")
Alternatively, you could change Expression.Constant(exp.ToString())
to be an invocation of ToString
on exp
, so that the ToString
executed when you invoke the expression.
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);
}
Which gives:
Print(c => ((c.LastName == "Doe") AndAlso ((c.FirstName == "John") OrElse (c.LastName == "Jane"))).ToString())