.NET平台开源项⽬速览(8)ExpressionEvaluator表达式计算
组件使⽤
在⽂章:中,给⼤家初步介绍了⼀下Expression Evaluator验证组件。那⾥只是概述了⼀下,并没有对其使⽤和强⼤功能做深⼊研究,所以今天就通过⼀篇简单的⽂章来预览⼀下其强⼤的功能。本⽂曾在【原创】.NET开源表达式计算组件介绍与使⽤⼀⽂中介绍过⼀个.NET平台开源的表达式计算组件NCal。不过经过⽐较还是这个Expression Evaluator⽐较强⼤,虽然部分功能有重叠。也都能计算常规的数学表达式。这个组件的功能应该说更加强⼤吧。同时上次的⽂章中,也有⽹友提到了另外⼀个在github的.NET平台的表达式计算组件。
.NET开源⽬录:
本⽂原⽂地址:
1.基本功能介绍
Expression Evaluator是⼀个轻量级的可以在运⾏时解析C#表达式的开源免费组件。表达式求值应该在很多地⽅使⽤,例如⼀些⼯资或者成本核算系统,就需要在后台动态配置计算表达式,从⽽进⾏计算求值。经过看源代码,这组件是⽤到了⼀个Antlr3的开源⼯具,Antlr3是⼀个开源的,⽀持多平台的语法解
析器。该组件⽬前还在更新中,所以值得关注。Expression Evaluator⽀持的特性有:
*⽀持算术运算符,⽀持关系运算符,以及逻辑运算符
*⽀持表达式分组和括号,以及递增递减运算符
*⽀持表达式属性访问以及动态类型,⽀持字符串的+运算
*⽀持数值类型的后缀d/f/m/l/u/ul、
*⽀持隐式表达式,以及成员访问操作符(.)
*⽀持⼀些默认的类型,如double, float, char, string, DateTime, Convert, Math
*⽀持foreach循环
等等,更多功能还期待你的使⽤和发现。下⾯我们就将介绍该组件的⼏个典型表达式求值的⽤途。
2.数学表达式求值
数学表达式求值应该是最常见的,⼀般我们在应⽤程序中如果需要计算,是需要对参数进⾏类型转换,
然后在后台进⾏相应计算的。但是如果是计算⼀些符合的式⼦或者公式,特别是参数不⼀定的情况下,这个就⽐较⿇烦,虽然也有解决办好。但总归是不好。那看看使
⽤ Expression Evaluator的⼏个简单例⼦。
使⽤需要注意的是:需要直接引⽤ExpressionEvaluator.dll,另外Antlr3.Runtime.dll可以直接引⽤,也可以直接放到bin⽬录中,否则会提⽰不到依赖⽂件。以前看到过⼀个表达式组件也是使⽤了这个开源的语法分析器。
看看核⼼代码,使⽤前引⽤主要的命名空间:using ExpressionEvaluator;
var expression = new CompiledExpression("1 + 2 + 3 + 4 + 5");
var result = expression.Eval();
Console.WriteLine(result);//结果 15
输出结果是 15,很明显就是2个过程,需要表达式,然后进⾏Eval分析计算即可。
另外在使⽤组件时,内部还默认注册了很多.NET值类型,可以直接使⽤这些类型的静态⽅法来进⾏操作。例如可以进⾏如下解析并执⾏:
var expression = new CompiledExpression("double.Parse('3.141592654')");
var result = expression.Eval();
Console.WriteLine(result); // 结果是:3.141592654
是可以直接执⾏double的Parse⽅法的。⽬前内置⽀持的类型:
object/Object,bool/Boolean,byte/Byte,char/Char,short/Int16,int/Int32,long/Int64,ushort/UInt16,uint/UInt32,ulon
double/Double,float/Single,string/String
⾄于布尔类型的判断等也都⽀持,⽐较简单,就不详细说了。
下⾯就看看Expression Evaluator的其他⽤法。进⾏简单数值计算,其他很多组件都能办到。
3.注册类型与范围注册类型的成员
在上⾯例⼦中,系统内部已经⽀持了⼀些数值类型,可以直接进⾏静态函数的调⽤解析。但是实际中,我们的业务系统类型肯定千变万
化,要满⾜动态计算的情况,显然上⾯是不够的。所以Expression Evaluator提供了这种⾮常给⼒的操作,将你的实例进⾏注册后,在表达
式中,可以直接使⽤注册的名称来访问实例的成员变量,然后参与表达式的计算。这样,很多复杂的动态计算功能基本都可以实现了。
看看下⾯这个例⼦,具体过程不详细见解,我在注释中写全⾯⼀点,看代码就可以理解了:
static void Test()
{
var v = new MyClass();//对象实例化
//TypeRegistry是核⼼的类型注册对象
var registry = new TypeRegistry();
//将上⾯的变量v进⾏注册,以符号vars替代
registry.RegisterSymbol("vars", v);
//表达式计算对象,仔细看⾥⾯的变量vars以及直接调⽤myExternalVar字段
var exp = new CompiledExpression("(ExternalVar + 3) / 2 * 4.5 ");
// 设置表达式的类型注册对象为 registry,注意要在eval之前进⾏设置
exp.TypeRegistry = registry;
Console.WriteLine(exp.Eval());//结果20.25,看看怎么来的?
//表达式计算对象,仔细看⾥⾯的变量vars以及直接调⽤myExternalVar字段
var exp2 = new CompiledExpression("RandomNumber() + 3");
// 设置表达式的类型注册对象为 registry,注意要在eval之前进⾏设置
exp2.TypeRegistry = registry;
Console.WriteLine(exp2.Eval());//结果为8,5+3
}
上⾯的MyClass类型的代码如下,很简单:
/// <summary>⾃定义的实体或者业务类型</summary>
public class MyClass
{
/// <summary>⼀个指定的double字段</summary>
public double myExternalVar;
//获取double值的⼀个⽅法
public double getRandomNumber()
{
return 5;//假设默认返回5
}
}
下⾯再看⼀下通过字符串访问数组索引值的⽅法。
4.通过字符串动态访问数组下标
和上⾯的例⼦有部分类似,开阔⼀下眼界吧,说明其使⽤是⾮常灵活的。为了便于演⽰,我们同样构造⼀个MyClass2类,代码如下:
public class MyClass2
writeline输出数值变量{
public string[] myExternalString;
public int x;
}
下⾯是访问获取字符串数组的代码:
var v = new MyClass2();
v.x = 2;
var registry = new TypeRegistry();
registry.RegisterSymbol("v", v);
var exp = new CompiledExpression("v.myExternalString[v.x/2]");
exp.TypeRegistry = registry;
Console.WriteLine(exp.Eval());//结果there
5.资源
源代码⼤家可以去官⽹下载最新的,还是⽼样⼦,制作了⼀份CHM格式的帮助⽂档。如果打不开的同学,记得右键,属性,解除锁定哦。晒图:
下载地址:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论