Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何获得表达式的值<;行动<;T>&燃气轮机;迅速行动?_C#_Linq_Expression - Fatal编程技术网

C# 如何获得表达式的值<;行动<;T>&燃气轮机;迅速行动?

C# 如何获得表达式的值<;行动<;T>&燃气轮机;迅速行动?,c#,linq,expression,C#,Linq,Expression,假设我们有以下代码: ExpressionHelper.GetRouteValuesFromExpression<AccountController>(ax => ax.MyAction("a", "b")); Expression<Func<object>> lambdaExpression = Expression.Lambda<Func<object>>(Expression.Convert(arg, typeof (ob

假设我们有以下代码:

ExpressionHelper.GetRouteValuesFromExpression<AccountController>(ax => ax.MyAction("a", "b"));
Expression<Func<object>> lambdaExpression = Expression.Lambda<Func<object>>(Expression.Convert(arg, typeof (object)));

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

value = func()
ExpressionHelper.getRouteValuesFroExpression(ax=>ax.MyAction(“a”、“b”);
(来自ASP.NET MVC程序集)。该方法相当快——它在150ms内执行10k次迭代

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

string a = "a";
string b = "b";
ExpressionHelper.GetRouteValuesFromExpression<AccountController>(ax => ax.MyAction(a, b));
string a=“a”;
字符串b=“b”;
ExpressionHelper.GetRouteValuesFromExpression(ax=>ax.MyAction(a,b));
此代码将在15秒内执行10k次迭代

问题在于以下代码:

ExpressionHelper.GetRouteValuesFromExpression<AccountController>(ax => ax.MyAction("a", "b"));
Expression<Func<object>> lambdaExpression = Expression.Lambda<Func<object>>(Expression.Convert(arg, typeof (object)));

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

value = func()
Expression lambdaExpression=Expression.Lambda(Expression.Convert(arg,typeof(object));
Func 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 …
}
字典m\u缓存=
新字典();
public void GetRouteValuesFromeExpression(表达式表达式){
Action=null;
如果(!m_Cache.TryGetValue(expr,ref compiled)){
compiled=expr.Compile();
m_Cached.Add(expr,compiled);
}
//执行…
}

如果这是一个瓶颈,为什么不在本地缓存表达式的值及其编译后的值呢?我想一本简单的字典可以做到这一点:

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 …
}
字典m\u缓存=
新字典();
public void GetRouteValuesFromeExpression(表达式表达式){
Action=null;
如果(!m_Cache.TryGetValue(expr,ref compiled)){
compiled=expr.Compile();
m_Cached.Add(expr,compiled);
}
//执行…
}

它必须是
函数吗?您可能可以手动创建一个“捕获”——即拥有一个声明a&b的类型;拥有一个
Func
,并将其编译为委托。那么您在运行时要做的就是:

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

我不太清楚Convert(废话,typeof(object))在做什么-你能澄清一下吗?我对表达式有相当多的经验,但这似乎。。。异常…

它必须是
函数吗?您可能可以手动创建一个“捕获”——即拥有一个声明a&b的类型;拥有一个
Func
,并将其编译为委托。那么您在运行时要做的就是:

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

我不太清楚Convert(废话,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
参数,这将为您提供反射字段,该字段将作为第一个参数传递给您的调用(
a
)。但是,我无法提取评估此字段所需的上下文(最后一行,位置用“…”标记)。我认为,如果不编译表达式,就无法访问此上下文。因此,你想要的是不可能的

请证明我错了


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

我做了一些调整,并得出以下结论:

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
参数,这将为您提供反射字段,该字段将作为第一个参数传递给您的调用(
a
)。但是,我无法提取评估此字段所需的上下文(最后一行,位置用“…”标记)。我认为,如果不编译表达式,就无法访问此上下文。因此,你想要的是不可能的

请证明我错了


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

我认为这不起作用。如果值不是常量,则表达式不包含值。所以,在我上面的例子中,您最终会为所有可能的a和b值缓存一个链接。是的,您是对的。对不起,我没有意识到价值观正在改变,这对我来说有点愚蠢。我认为这不起作用。如果值不是常量,则表达式不包含值。所以,在我上面的例子中,您最终会为所有可能的a和b值缓存一个链接。是的,您是对的。很抱歉,我没有意识到值正在更改,这对我来说有点愚蠢。这是来自ASP.NET MVC futures assembly的代码,在Moq中使用相同的代码来获取参数的值,所以我猜这是“官方方法”。我问这个问题是因为这种行为将我们网站中的请求数量减少了2.5倍……这是来自ASP.NET MVC futures assembly的代码,在Moq中使用相同的代码来获取参数值,所以我猜这是“官方方法”。我问这个问题是因为这种行为将我们网站中的请求数量减少了2.5倍。。。