从单个参数获取Func <T>和Expression <Func <T >>?

我想获得编译的Func(布尔)和一个 表达式(的Func(的布尔))使用一个单一的参数。我不打算修改 表达树。完全采用表达式树的唯一原因 是这样我可以打印出正在执行的代码。

void Assert(Expression> assertionExpression) {
    if (!assertionExpression.Compile()()) 
    { 
        throw new AssertFailedException(assertionExpression.ToString()); 
    }
}

有没有合理的方法来做到这一点?

作为一种证明,在简单的编译器生成的表达式树的情况下,是否将同一个实例始终作为参数传递?

static Dictionary>, Func> cache;

static void Assert(Expression> assertionExpression) {
    Func 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

1 答案

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

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

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

为了使它和缓存一起工作并编译,你可以在表达式上使用.ToString()来得到函数的字符串表示形式,但是如果你有任何闭包,这可能会引起非常混乱的问题,因为字符串表示可能是相同的,但是,关闭的变量会有所不同,所以如果你这样做,请谨慎使用!

0
额外