English 中文(简体)
如何快速获取Expression <Action <T>>操作的值?
原标题:
  • 时间:2008-10-20 13:33:06
  •  标签:

假设我们有以下代码:

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

从ASP.NET MVC Futures程序集中翻译:该方法相当快 - 在150毫秒内执行10,000次迭代。

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

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

这段代码将在15秒内执行1万次迭代。

问题是以下代码:

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

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

value = func()

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

问题回答

为什么不把表达式的值和编译值本地化缓存起来,如果这是一个瓶颈的话?我想一个简单的字典就可以搞定:

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

它必须是一个Func<object>吗?你可能可以手动制作一个“捕获”——即声明a和b的类型;有一个Func<Whatever, object>,然后将其编译为委托。然后,在运行时您所做的全部操作是:

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

我不太确定Convert(blah,typeof(object))正在做什么-您能说明一下吗?我在表达式方面有相当多的经验,但这似乎......不寻常......

我稍微摆弄了一下,得出了以下结果:

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)。但是,我无法提取评估此字段所需的上下文(最后一行,“…”标记的位置)。我相信这个上下文不能在表达式编译之前访问。因此,您想要的是不可能的。

请证明我错了。;-)

实际上,我并不确定,因为即使使用反射器,我也无法找到执行上下文正在存储的位置,所以我可能会忽略某些内容。





相关问题
热门标签