16

编译时Expression<T>,结果代码是否被框架隐式缓存?我正在考虑Regex框架隐式编译和缓存最后几个正则表达式的静态方法。

如果Expression<T>缓存已编译的对象,您能否推荐一些最佳实践来降低编译时间或在我手动缓存表达式时可能导致问题的任何陷阱?

public MyResultType DoSomething(int arg1, int arg2)
{
    var result = invokeHandler(
        (IDoSomethingHandler h) => h.DoSomething(arg1, arg2)
    );
    return result;
}

private TResult invokeHandler<T, TResult>(Expression<Func<T, TResult>> action)
    where T : class
{
    // Here, I might want to check to see if action is already cached.

    var compiledAction = action.Compile();
    var methodCallExpr = action as MethodCallExpression;

    // Here, I might want to store methodCallExpr in a cache somewhere.

    var handler = ServiceLocator.Current.GetInstance<T>();
    var result = compiledAction(handler);

    return result;
}

在这个例子中,我有点担心如果我缓存编译的表达式,它会使用 和 的值,arg1因为arg2它们在编译表达式时,而不是从堆栈中的适当位置检索这些值(即而不是获取当前值)。

4

2 回答 2

11

不; 我不相信它是;如果你想缓存它,你必须保留Delegate引用(通常是Func<...>Action<...>)。同样,如果您想获得最佳性能,您可以将其编译为参数化表达式,以便在调用它时发送不同的值。

在这种情况下,重新措辞会有所帮助:

public MyResultType DoSomething(int arg1, int arg2)
{
    var result = invokeHandler(
        (IDoSomethingHandler h, int a1, int a2) => h.DoSomething(a1, a2),
        arg1, arg2);
    return result;
}

private TResult invokeHandler<T, TResult>(Expression<Func<T,int,int,TResult>> action,
    int arg1, int arg2)
    where T : class
{
    // Here, I might want to check to see if action is already cached.

    var compiledAction = action.Compile();
    var methodCallExpr = action as MethodCallExpression;

    // Here, I might want to store methodCallExpr in a cache somewhere.

    var handler = ServiceLocator.Current.GetInstance<T>();
    var result = compiledAction(handler, arg1, arg2);

    return result;
}

即制作表达式的数字参数,并在运行时传递实际的参数(而不是表达式中的常量)。

于 2008-11-03T15:02:04.537 回答
2

Lambda experssions 不会自动缓存。您将需要为此实现自己的缓存/记忆算法。检查相关的 Stackoverflow 问题:

是否可以缓存在 lambda 表达式中评估的值?

需要注意的是,lambda 表达式在 C# 中是惰性求值的。

于 2008-11-03T15:02:43.460 回答