C# 具有返回值的动态Linq表达式
我需要创建一个动态linq表达式,我开始使用许多示例。我测试了一些工作,一些没有。在本例中,我希望创建一个如下所示的方法:C# 具有返回值的动态Linq表达式,c#,expression-trees,C#,Expression Trees,我需要创建一个动态linq表达式,我开始使用许多示例。我测试了一些工作,一些没有。在本例中,我希望创建一个如下所示的方法: public bool Check(int intvar) { if ( i > 2 ) return true; else return false; } 现在我写了以下内容: LabelTarget returnTarget = Expression.Label("label"); ParameterExpression para
public bool Check(int intvar)
{
if ( i > 2 )
return true;
else
return false;
}
现在我写了以下内容:
LabelTarget returnTarget = Expression.Label("label");
ParameterExpression para = Expression.Parameter(typeof(int), "intvalue");
Expression test = Expression.GreaterThan(para, Expression.Constant(5));
Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
Expression iffalse = Expression.Return(returnTarget, Expression.Constant(false));
Expression.IfThenElse(test, iftrue, iffalse);
this.TheExpression = Expression.IfThenElse(test, iftrue, iffalse);
Expression.Lambda<Action<int>>(
this.TheExpression,
new ParameterExpression[] { para }
).Compile()(5);
labelTargetReturnTarget=Expression.Label(“Label”);
ParameterExpression para=表达式参数(typeof(int),“intvalue”);
表达式测试=表达式大于(第段,表达式常数(5));
表达式iftrue=Expression.Return(returnTarget,Expression.Constant(true));
表达式iffalse=Expression.Return(returnTarget,Expression.Constant(false));
表达式.IfThenElse(测试、iftrue、iffalse);
this.TheExpression=Expression.ifthenels(test,iftrue,iffalse);
Lambda(
这个表达,
新参数表达式[]{para}
).Compile()(5);
现在,它抛出InvalidOperationException:
无法跳转到标签“label”`
怎么了?我只需要返回true或false。
returnTarget
当前仅由if/then/else语句引用。标签不会放置在语句中的任何位置。所以它不知道跳到哪里。仅定义和引用标签,而不放置标签
尝试使用Expression.Block
组合lambda和标签
Expression.Lambda<Action<int>>(
Expression.Block(
this.TheExpression,
Expression.Label(returnTarget)
),
new ParameterExpression[] { para }
).Compile()(5);
Expression.Lambda(
表达式块(
这个表达,
Expression.Label(返回目标)
),
新参数表达式[]{para}
).Compile()(5);
我还没有测试过,但这是你可以找到答案的大致方向
-更新-测试它,上面的lambda编译和运行就像现在一样
-update2-显然,您也想返回一个值,让我看看,至少,它应该是
Func
而不是Action
,您需要更改一些内容:
- 按照Rene的建议,将返回标签放在块表达式中函数的底部。这是您的
语句将跳转的地方return
- 将Lambda声明为type
。因为您需要返回值,所以它需要是一个函数,而不是一个操作Func
- 将
标签声明为typereturnTarget
。由于块表达式的返回值是其最后一条语句的值,因此标签的类型必须正确bool
- 为最终标签提供默认值(=如果通过正常控制流而不是
语句到达标签,则函数的返回值)return
labelTargetReturnTarget=Expression.Label(typeof(bool)); ParameterExpression para=表达式参数(typeof(int),“intvalue”); 表达式测试=表达式大于(第段,表达式常数(5)); 表达式iftrue=Expression.Return(returnTarget,Expression.Constant(true)); 表达式iffalse=Expression.Return(returnTarget,Expression.Constant(false)); var ex=Expression.Block( 表达式IfThenElse(测试、iftrue、iffalse), Expression.Label(returnTarget,Expression.Constant(false)); var compiled=Expression.Lambda( 前任, 新参数表达式[]{para} ).Compile(); Console.WriteLine(已编译(5));//打印“假” Console.WriteLine(已编译(6));//打印“真实”
if(条件)
返回表达式1;
其他的
返回表达式2;
您可以将其转换为三元表达式:条件?表达式1:expression2
。
然后可以创建表达式,而无需使用Label
、Return
或Goto
表达条件;
表达1;
表达2;
/* ... */
表达式体=表达式.条件(
测试:条件,
如果真的是这样:表达1,
ifFalse:表达式2);
您能再告诉我们一些您想要实现的目标吗?例如,为什么需要动态创建此表达式。。。为什么需要使用标签以及if\else何时可以编写:public bool Check(int intvar){return i>2;}如果查看一些编译后的IL代码,您会发现它从未真正离开过…;)
LabelTarget returnTarget = Expression.Label(typeof(bool));
ParameterExpression para = Expression.Parameter(typeof(int), "intvalue");
Expression test = Expression.GreaterThan(para, Expression.Constant(5));
Expression iftrue = Expression.Return(returnTarget, Expression.Constant(true));
Expression iffalse = Expression.Return(returnTarget, Expression.Constant(false));
var ex = Expression.Block(
Expression.IfThenElse(test, iftrue, iffalse),
Expression.Label(returnTarget, Expression.Constant(false)));
var compiled = Expression.Lambda<Func<int, bool>>(
ex,
new ParameterExpression[] { para }
).Compile();
Console.WriteLine(compiled(5)); // prints "False"
Console.WriteLine(compiled(6)); // prints "True"