表达式引擎 v2.5.2+
框架集成了 Yacep 表达式引擎,提供了在运行时执行表达式的能力。
表达式为单行字符串,在开发时编写或由用户配置。在运行时基于指定对象获取数据或执行操作。在某些场景下,表达式解析执行是必不可少的功能。例如要实现一个基于特性(Attribute)的缓存操作功能,它可以基于方法参数生成缓存键,但在编写功能实现时根本无法预知参数的名称、数量、结构。这时只能由使用此功能的开发人员通过表达式指定参数信息,然后在运行时执行表达式来获取实际的参数值。
下面对 Yacep 的语法和功能作简要介绍,更多内容请查看官方文档。
语法
字面量
- 数字:如 12、-90、8.9
- 字符串:如 'hello'、"world"。可以使用单引号或双引号, 不过表达式本身已经是字符串,因此通常使用单引号避免转义。
- 数组:如 [1, 2, 3]
- 布尔值:true、false
- 空值:null
运算符
- 逻辑运算:&&、||、!
- 数值运算:+、-、*、/、%
- 比较运算:==、!=、>、<、>=、<=
- 条件运算:? :
- 包含运算:in
- 判断给定值是否在指定范围内,例如 "5 in (1, 3, 5)"
- 成员访问:
.
- 访问对象的属性、字段、方法,例如 "user.Name"、"user.Smile()"、
- 索引器:[]
- 访问数组或字典项值,例如 "arr[0]"、"dict['key']"
- 如果操作数为对象,同
.
运算符。
注意
+
运算符支持字符串拼接,但要求两边操作数必须全部为字符串类型。
注意
访问对象成员时,严格区分大小写。
裸函数
裸函数即不挂载在任何对象上,可以直接调用的函数,通常提供全局通用的辅助功能。Yacep 内置了一些裸函数。
统计类
- len:获取集合的长度
- max:统计数组中的最大值
- min:统计数组中的最小值
- sum:统计数组元素和
- avg:统计数组元素均值
日期类
- now:获取当前日期及时间,支持指定格式。默认格式为yyyy/MM/dd HH:mm:ss
- 例如 "now('yyyy-MM-dd HH:mm')"
- today:获取当前日期,支持指定格式。默认格式为yyyy/MM/dd
- 例如 "today('yyyy-MM-dd')"
- time:获取当前时间,支持指定格式。默认格式为HH:mm:ss
- year:获取当前年
- month:获取当前月
- day:获取当前日
- hour:获取当前小时
- minute:获取当前分钟
- second:获取当前秒
执行
速览
Yacep 表达式的解析执行非常简单,调用其提供的扩展方法即可,请看以下示例。
csharp
// 2
int result = "1 + 1".Compile().EvaluateAs<int>();
// hello,world
string result = "'hello,' + 'world'".Compile().EvaluateAs<string>();
// true
bool result = "[1,2,3][0] == 1".Compile().EvaluateAs<string>();
// 2
int result = "sum([1, 1])".Compile().EvaluateAs<int>();
上下文对象
如果仅能像上例那样执行表达式,似乎作用有限——看起来无法访问运行时数据。 于是 Yacep 提供了重载方法,支持传入上下文对象参数。
有了上下文对象,我们就可以在表达式中对其进行操作、访问属性、调用方法,极大地扩展了表达式的应用场景。
Yacep 仅支持传入一个根对象,我们可以根据需要将多个参数封装到一个匿名类对象中。
csharp
Foo foo = new Foo { Id = "001", Name = "Max" };
// true
bool result = "p.Id == '001' && p.Name == 'Max'"
.Compile().EvaluateAs<string>(new { p = foo });
函数扩展
Yacep 支持自定义裸函数,下面给出一个示例,功能是将入参转化为字符串。
csharp
private static readonly ReadOnlyParseOption option = ParseOption.CreateOption()
.AddNakedFunction("str",
(object[] args) => args.Length > 0 ? Convert.ToString(args[0]) : ""
)
.AsReadOnly();
// hello,233
string result = "'hello,' + str(233)".Compile(option).EvaluateAs<string>();
上例中创建了一个静态配置对象 option,在其中添加了自定义函数 str
,然后传递给 Compile 方法使用。这里函数使用了 lambda 表达式实现,如果方法复杂则建议编写单独的完整方法。
注意
自定义函数只能有一个 object[]
参数,包含所有传入的参数。使用时注意转换参数类型。