如何获得Expression <action <t>的价值&gt;行动很快?</action <t>

时间:2008-10-20 13:33:06

标签: c# linq expression

假设我们有以下代码:

ExpressionHelper.GetRouteValuesFromExpression<AccountController>(ax => ax.MyAction("a", "b"));

(来自ASP.NET MVC Futures程序集)。方法相当快 - 它在150ms内执行10k次迭代。

现在,我们将代码更改为:

string a = "a";
string b = "b";
ExpressionHelper.GetRouteValuesFromExpression<AccountController>(ax => ax.MyAction(a, b));

此代码将在15 秒内执行10k次迭代

问题是以下代码:

Expression<Func<object>> lambdaExpression = Expression.Lambda<Func<object>>(Expression.Convert(arg, typeof (object)));

Func<object> func = lambdaExpression.Compile();

value = func()

有没有更好的方法从表达式获取值而不是每次编译表达式?这可以极大地影响ASP.NET MVC链接生成速度。

3 个答案:

答案 0 :(得分:1)

为什么不在本地缓存表达式的值及其编译值?如果这是一个瓶颈?我想一个简单的词典可以解决这个问题:

Dictionary<Expression<Action<T>>, Action<T>> m_Cache =
    new Dictionary<Expression<Action<T>>, Action<T>>();

public void GetRouteValuesFromExpression<T>(Expression<Action<T>> expr) {
    Action<T> compiled = null;
    if (!m_Cache.TryGetValue(expr, ref compiled)) {
        compiled = expr.Compile();
        m_Cached.Add(expr, compiled);
    }
    // execute …
}

答案 1 :(得分:0)

是否必须是Func<object>?您可以手动制作“捕获” - 即具有声明&amp; b;有Func<Whatever, object>,并将其编译为委托。然后你在运行时所做的就是:

Foo foo = new Foo {A = a, B = b};
return cachedFunc(foo);

我不太确定Convert(blah,typeof(object))正在做什么 - 你能澄清一下吗?我对表达方式有很多经验,但这似乎......不寻常......

答案 2 :(得分:0)

我已经摆弄了一下,想出了以下内容:

var body = (MethodCallExpression)expr.Body;
var arg1 = (MemberExpression)body.Arguments[0];
var contextType = arg1.Member.DeclaringType;
var field = contextType.GetField(arg1.Member.Name);
Console.WriteLine(field.GetValue(…));

假设expr是您的Expression<Action<T>>参数,这会为您提供反射字段,该字段作为您调用的第一个参数传递(在您的情况下为a)。但是,我无法提取评估此字段所需的上下文(最后一行,标有“...”的位置)。我相信如果没有汇编表达式,就无法访​​问这个上下文。因此,你想要的是不可能的。

证明我错了。 ; - )

(实际上,我不太确定,因为即使使用Reflector我也无法找到存储执行上下文的位置,所以我可能会忽略某些内容。)