获取Func <t>和表达式<func <t>&gt;来自单个参数?</func <t> </t>

时间:2012-05-24 15:54:01

标签: c#

我想得到编译的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();
}

输出是'缓存插入',缓存命中','缓存命中'还是'缓存插入','缓存插入','缓存插入'。

1 个答案:

答案 0 :(得分:1)

对于第一个问题,您可以使用表达式树并对其进行编译以获得可执行版本,但每次都会重新编译,因此您必须对其进行缓存。

static void Assert(Expression<Func<bool>> assertionExpression) {
    var func = assertionExpression.Compile(); // if you call func() it will execute the expression
}

对于你的第二个问题,它每次都是一个新的表达式树,所以你将得到“缓存插入”“缓存插入”“缓存插入”等...

为了使它能够使用缓存并进行编译,你可以在表达式上使用.ToString()来获取函数的字符串表示形式,但如果你有任何闭包,这可能会导致非常混乱的问题,因为字符串表示可能是相同但封闭的变量会有所不同,所以如果你这样做,请谨慎使用!