我想得到编译的Func(布尔值)和一个 使用单个参数表达(Func(of boolean))。我不打算修改 表达树。完全采用表达式树的唯一原因 是这样我可以打印出正在执行的代码。
void Assert(Expression<Func<bool>> assertionExpression) {
if (!assertionExpression.Compile()())
{
throw new AssertFailedException(assertionExpression.ToString());
}
}
有没有合理的方法可以做到这一点?
作为一个证据,在简单编译生成表达式树的情况下,同一个实例是否总是作为参数传递?
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();
}
输出是'缓存插入',缓存命中','缓存命中'还是'缓存插入','缓存插入','缓存插入'。
答案 0 :(得分:1)
对于第一个问题,您可以使用表达式树并对其进行编译以获得可执行版本,但每次都会重新编译,因此您必须对其进行缓存。
static void Assert(Expression<Func<bool>> assertionExpression) {
var func = assertionExpression.Compile(); // if you call func() it will execute the expression
}
对于你的第二个问题,它每次都是一个新的表达式树,所以你将得到“缓存插入”“缓存插入”“缓存插入”等...
为了使它能够使用缓存并进行编译,你可以在表达式上使用.ToString()来获取函数的字符串表示形式,但如果你有任何闭包,这可能会导致非常混乱的问题,因为字符串表示可能是相同但封闭的变量会有所不同,所以如果你这样做,请谨慎使用!