编译 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 的值,因为它们当时是编译表达式,而不是从堆栈中的适当位置检索这些值(即,而不是获取当前值)。

有帮助吗?

解决方案

没有;我不相信它;如果你想要它被缓存,你必须保持 Delegate 引用(通常是 Func&lt; ...&gt; Action&lt; ...&gt; )。同样,如果你想获得最佳性能,你可以将它编译为参数化表达式,这样你就可以在调用它时发送不同的值。

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

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;
}

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

其他提示

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top