Reputation: 2041
I would like to get both the compiled Func(of boolean) and an Expression( of Func(of boolean)) using a single parameter. I don't intend to modify the expression tree. The only reason to take an Expression tree at all is so i can print out the code that is being executed.
void Assert(Expression<Func<bool>> assertionExpression) {
if (!assertionExpression.Compile()())
{
throw new AssertFailedException(assertionExpression.ToString());
}
}
Is there any reasonable way to do this?
As a corrolarry, in the case of simple compiler generated expression trees, will the same instance always be passed as a parameter?
static Dictionary<Expression<Func<bool>>, Func<bool>> cache;
static void Assert(Expression<Func<bool>> assertionExpression) {
Func<bool> method = null;
if (!cache.TryGetValue(assertionExpression, out method)) {
cache.Add(assertionExpression, method = assertionExpression.Compile());
Console.WriteLine("cache insert");
}
else {
Console.WriteLine("cache hit");
}
if (!method())
{
throw new AssertFailedException(assertionExpression.ToString());
}
}
static void someCodeThatExecutesRegularly() {
Assert(()=>true);
}
public static void Main(string[] args, int argc)
{
someCodeThatExecutesRegularly();
someCodeThatExecutesRegularly();
someCodeThatExecutesRegularly();
}
Will the output be 'cache insert, 'cache hit', 'cache hit' or 'cache insert', 'cache insert', 'cache insert'.
Upvotes: 1
Views: 236
Reputation: 5679
For the first question, you can take the expression tree and compile it to get an executable version, although it will recompile each time so you would have to cache it.
static void Assert(Expression<Func<bool>> assertionExpression) {
var func = assertionExpression.Compile(); // if you call func() it will execute the expression
}
For your second question, it will be a new expression tree each time, so you will get "cache insert" "cache insert" "cache insert" etc...
To get it working with the cache and compiling you could possibly use .ToString() on the expression to get the string representation of the function, but this could cause very confusing issues if you have any closures because the string representation could be the same but the closed variables would be different, so if you do do this, USE WITH CARE!
Upvotes: 1