我有一种情况,我读取业务逻辑并将变量替换为实际值,然后我需要对其进行评估以获得结果。我目前正在使用 bcParser 来执行此操作,它对于所有像 excel 格式一样编写的逻辑都可以正常工作。
向我抛出的曲线球是,if 条件不会像 excel 那样if(cond, true, false)
相反,它会像 C# 一样if (cond) { true; } else { false;}
,这更有意义并且易于维护。由于我事先用值替换了所有变量,所以我所要做的就是评估它。目前,我正在通过将逻辑导出到 c# 方法并使用反射来解决这个问题,我正在评估它,它也有效。
我想知道是否还有其他选择,我不想为每个 if 条件编写代码,并且想在运行时对其进行评估。我想知道是否应该能够创建某种令牌解析器并调用 C# 本机表达式求值并执行计算。我还没有深入理解表达式树,这种方法似乎是可能的。在我去那里之前,我想知道这可能吗?
谢谢,
Yes!
关键是使用System.Linq.Expressions
命名空间。您可以通过编程方式构建表达式树,无论是在代码中还是通过修改解析器,然后将其编译为Delegate
。这个API编译你的Delegate
里面的一个DynamicAssembly
这意味着当您完全取消引用编译的表达式时,垃圾收集器可以将它们从内存中卸载。
这是一个非常简单的例子:
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 代码生成(需要另一个进程来进行编译)要快得多,并且它的主要优点是生成可卸载的程序集。
唯一的限制是您无法使用此 API 创建类型。你必须限制自己的表达和陈述。不过它的功能相当强大,这就是 DLR 的神奇之处。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)