是否可以为动态if语句创建表达式树? [英] Is it possible to create an expression tree for dynamic if statements?

查看:49
本文介绍了是否可以为动态if语句创建表达式树?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个情境,我在其中读取业务逻辑并将变量替换为实际值,然后需要对其进行评估以获得结果.我目前正在使用bcParser做到这一点,并且对于所有像excel格式编写的逻辑都可以正常工作.

I have a situtaiton where I read the bussiness logic and replace the variables with actual values and then I need to evaluate it to get result. I am currently using bcParser to do it and it works just fine for all the logic which is written like excel format.

向我抛出的曲线球是,if条件将不像excel if(cond, true, false)而是if (cond) { true; } else { false;}那样的C#,这更有意义并且更易于维护.因为我事先用值替换了所有变量,所以我要做的就是评估它.目前,我正在通过将逻辑导出到c#方法并使用反射来解决此问题,我正在对其进行评估,它也可以正常工作.

The curve ball thrown at me is that, the if condition will not be like excel if(cond, true, false) rather it will be like C# where the if (cond) { true; } else { false;}, this makes more sense and easy to maintain. Since I replace all the variables with value before hand, all I have to do is evaluate it. Currently I am solving this problem by exporting the logic to c# methods and using reflection I am evaluating it and it also works.

我想知道是否还有其他选择,我不想为每个if条件编写代码,而是希望在运行时对其进行评估.我想知道我是否应该能够创建某种令牌解析器并调用C#本机表达式评估并执行计算.我还没有深入了解表达树,似乎可以采用这种方法.在我去那里之前,我想知道有没有可能? 谢谢,

I am wondering is there any other option, I do not want to write code for each if condition and would like to evaluate it on the run time. I was wondering if I should able to create a token parser of some sort and call C# native expression evalution and perform the calculation. I haven't gone into understanding expresion trees, it seems it is possible with that approach. before I go there, I would like to know is it possible at all? Thanks,

推荐答案

是!

键正在使用System.Linq.Expressions名称空间.您可以在代码中或通过修改解析器,以编程方式构建表达式树,然后将其编译为Delegate.此API在DynamicAssembly内编译Delegate,这意味着当完全取消引用编译的表达式时,垃圾回收器可以将其从内存中卸载.

The key is using the System.Linq.Expressions namespace. You can build up an expression tree programmatically, either in your code or by modifying your parser then compile it into a Delegate. This API compiles your Delegate inside of a DynamicAssembly which means that your compiled expressions can be unloaded from memory by the garbage collector when you completely dereference them.

这是一个非常简单的示例:

Here is a very simple example:

var b = true;
Func<bool> condition = () => b;
Action trueExpression = () => { Console.WriteLine(true); };
Action falseExpression = () => { Console.WriteLine(false); };

var e = Expression.Condition(
    Expression.Invoke(Expression.Constant(condition)),
    Expression.Invoke(Expression.Constant(trueExpression)),
    Expression.Invoke(Expression.Constant(falseExpression)));

var λ = Expression.Lambda(e).Compile();

b = true;
λ.DynamicInvoke();

b = false;
λ.DynamicInvoke();

这将产生输出:

True
False

将表达式编译为Lambda的步骤可能会严重影响性能,您将需要为已编译的Lambda提出一种缓存策略.不过,这样做非常值得,使用DynamicInvoke调用编译的lambda非常快.几乎就像您预先编译它一样快.该技术比使用CodeDom代码生成(后者需要一个完整的过程来进行编译)快得多,并且具有产生可卸载程序集的主要优点.

The step where the expression is compiled into a Lambda can be a significant performance hit, you will want to come up with a caching strategy for your compiled lambdas. It's well worth it though, calling the compiled lambda using DynamicInvoke is very fast. Almost as fast as if you had pre-compiled it. This technique is significantly faster than using CodeDom code generation (which requires a whole another process to do the compilation) and it has the major benefit of producing unloadable assemblies.

对此的唯一限制是您不能使用此API创建类型.您必须限制自己使用表达式和语句.它非常强大,这是DLR的魔力所在.

The only limitation to this is that you cannot create Types with this API. You have to limit yourself to expressions and statements. It's quite powerful however, this is the magic guts of the DLR.

这篇关于是否可以为动态if语句创建表达式树?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆