为自己的软件增加脚本编写功能并自定义API
Posted 足球中国
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为自己的软件增加脚本编写功能并自定义API相关的知识,希望对你有一定的参考价值。
CBScript语法介绍
开发背景:为ERP系统统计报表提供用户定义的公式,生成复杂的数据及表格内容。做一定的二次开发。
为什么不使用动态编译:因为有些函数需要在服务器端执行,执行时有安全风险,比如错误或者有意的编程,删除服务器的文件
使用方法 项目添加引用 [DataUtils.v1.1.dll]
CBScript支持的语法
1、支持变量定义
var s="Hello World";
var i=100
2、支持的语句
While循环语句 以While开始,EndWhile结束
long target = 100;
string str = @"
VAR A=1
WHILE A<100
A=A+1
ENDWHILE
RETURN A
";
FunctionBody function = new FunctionBody();
object value = function.Exec(str);
Assert.AreEqual(target, value);
Foreach语句
string str =
@"//定义变量
VAR LIST=LISTNEW(1,2,3,4,5,6,7)
//设置标签
FOREACH A IN LIST
IF A>5
RETURN A
ENDIF
ENDFOREACH
";
DataExcel grid = Grid;
FunctionBody script = ScriptBuilder.BuilderScript(grid, grid.FocusedCell);
object result = Feng.Utils.ConvertHelper.ToInt32(script.Exec(str));
object target = 6;
Assert.AreEqual(target, result);
For语句 以for开始以endfor结束
string str =
@"//
var sum=0;
var i=0;
for i=0;i<10;i=i+1;
if i%5==1
sum=sum+i;
endif
endfor
return sum;
";
string target = "7";
string result = "";
DataExcel grid = Grid;
FunctionBody script = ScriptBuilder.BuilderScript(grid, grid.FocusedCell);
script.StateMentFactory = new StateMentFactory();
object value = script.Exec(str);
result = Feng.Utils.ConvertHelper.ToString(value);
Assert.AreEqual(target, result);
IF ELSE语句 以IF开始 ENDIF结束
string str =
@"//Return
IF 3<2
RETURN CELLVALUE(""INDEX"")
ELSE 3<3
RETURN CELLVALUE(""INDEX"")+100
ELSE
RETURN CELLVALUE(""INDEX"")+200
ENDIF
";
DataExcel grid = Grid;
FunctionBody script = ScriptBuilder.BuilderScript(grid, grid.FocusedCell);
int target = 100;
grid[2, 2].Value = target;
grid[2, 2].ID = "INDEX";
script.StateMentFactory = new StateMentFactory();
int result = Feng.Utils.ConvertHelper.ToInt32(script.Exec(str)) - 200;
Assert.AreEqual(target, result);
Return 语句
string str =
@"//Return
IF 1<2
RETURN CELLVALUE(""INDEX"")
ENDIF
";
DataExcel grid = Grid;
FunctionBody script = ScriptBuilder.BuilderScript(grid, grid.FocusedCell);
int target = 100;
grid[2, 2].Value = target;
grid[2, 2].ID = "INDEX";
script.StateMentFactory = new StateMentFactory();
int result = Feng.Utils.ConvertHelper.ToInt32(script.Exec(str));
Assert.AreEqual(target, result);
注释语句 以//开头
// 循环100次
FOR I=0;I<100;I=I+1
ENDFOR
3、删除不需要的API函数
通过SimpleFunctionBody.CBMethod.Methods可以删除通过 InitDefaultFunction函数预加载的API
也可以不调用 InitDefaultFunction不加载自定义使用下面列API可以自由添加或者自定义
this.CBMethod.Methods.Add(new StringFunctionContainer());
this.CBMethod.Methods.Add(new DateTimeFunctionContainer());
this.CBMethod.Methods.Add(new FileFunctionContainer());
this.CBMethod.Methods.Add(new ConvertFunctionContainer());
this.CBMethod.Methods.Add(new MathematicsFunctionContainer());
this.CBMethod.Methods.Add(new TrigonometricFunctionContainer());
this.CBMethod.Methods.Add(new ArrayFunction());
this.CBMethod.Methods.Add(new ListFunctionContainer());
this.CBMethod.Methods.Add(new DataTableFunctionContainer());
this.CBMethod.Methods.Add(new SqlServerFunctionContainer());
this.CBMethod.Methods.Add(new WebServiceFunctionContainer());
this.CBMethod.Methods.Add(new FormFunctionContainer());
this.CBMethod.Methods.Add(new ConsoleFunctionContainer());
this.CBMethod.Methods.Add(new StyleFunctionContainer());
this.CBMethod.Methods.Add(new XMLFunctionContainer());
this.CBMethod.Methods.Add(new JsonFunctionContainer());
this.CBMethod.Methods.Add(new ReflectionContainer());
如果对运算符有特殊处理,可以通过继承ExcuteProxy重写运算符操作。
4、自定义API
自定义API有两种方式:
4.1 定义函数 将函数加入 API
public void SimpleFunctionBody_Test_Custom()
int a = 6 % 3 << 4 * 20;
int target = 1 + 2 + 3 + 4 + 2 + 6 % 3 << 4 * 20 + (12 - 32) + 100;
string str = @"1+2+3+4+2+6%3<<4*20+(12-32)+Custom()";
SimpleFunctionBody function = new SimpleFunctionBody();
function.Add(new BaseMethod() Function = CustomFunction, Name = "Custom" );
object value = function.Exec(str);
Assert.AreEqual(target, value);
public object CustomFunction(object[] args)
return 100;
4.2 定义一个函数集合类,将整个函数集合加入到 API
using Feng.Collections;
using Feng.Script.CBEexpress;
using Feng.Script.Method;
using System;
using System.Collections.Generic;
namespace Feng.Script.FunctionContainer
[Serializable]
public class ArrayFunction : CBMethodContainer
public const string Function_Category = "ArrayFunction";
public const string Function_Description = "数组";
public override string Name
get return Function_Category;
public override string Description
get return Function_Description;
public ArrayFunction()
BaseMethod model = null;
model = new BaseMethod();
model.Name = "ArrayInit";
model.Description = "创建一个集合 VAR Array =ArrayInit(1,2,3,4,5,6)";
model.Eg = @"VAR Array =ArrayInit(1,2,3,4,5,6)";
model.Function = ArrayInit;
MethodList.Add(model);
model = new BaseMethod();
model.Name = "ArrayNew";
model.Description = "创建一个集合 VAR Array =ArrayNew(10)";
model.Eg = @"VAR Array =ArrayNew(10)";
model.Function = ArrayNew;
MethodList.Add(model);
model = new BaseMethod();
model.Name = "ArrayCount";
model.Description = "返回集合长度";
model.Eg = @"ArrayCount(LIST)";
model.Function = ArrayCount;
MethodList.Add(model);
model = new BaseMethod();
model.Name = "ArrayIndex";
model.Description = @"返回集合的第某个值 ListIndex(ARRAY,3)";
model.Eg = @"ArrayIndex(ARRAY,3)";
model.Function = ArrayIndex;
MethodList.Add(model);
model = new BaseMethod();
model.Name = "ArrayCopy";
model.Description = "复制一个集合 ArrayCopy(ARRAY)";
model.Eg = @"ArrayCopy(ARRAY)";
model.Function = ArrayCopy;
MethodList.Add(model);
public virtual object ArrayInit(params object[] args)
object[] list = new object[args.Length - 1];
for (int i = 1; i < args.Length; i++)
list[i - 1] = args[i];
return list;
public virtual object ArrayNew(params object[] args)
int count = base.GetIntValue(1, args);
return new object[count]; ;
public virtual object ArrayCount(params object[] args)
object[] list = base.GetArgIndex(1, args) as object[];
return list.Length;
public virtual object ArrayIndex(params object[] args)
object[] list = base.GetArgIndex(1, args) as object[];
if (list == null)
return null;
int index = base.GetIntValue(2, args);
if (args.Length > 3)
object value = base.GetArgIndex(3, args);
list[index] = value;
else
return list[index];
return null;
public virtual object ArrayCopy(params object[] args)
object[] list = base.GetArgIndex(1, args) as object[];
return list.Clone();
public void SimpleFunctionBody_Test_Custom()
int a = 6 % 3 << 4 * 20;
int target = 1 + 2 + 3 + 4 + 2 + 6 % 3 << 4 * 20 + (12 - 32) + 100;
string str = @"1+2+3+4+2+6%3<<4*20+(12-32)+Custom()";
SimpleFunctionBody function = new SimpleFunctionBody();
//将一个函数加入API
function.Add(new BaseMethod() Function = CustomFunction, Name = "Custom" );
//将定义的函数集合加入到API
function.Add(new ArrayFunction());
object value = function.Exec(str);
Assert.AreEqual(target, value);
4、系统预置的API 包括XML处理,数组函数,List集合函数,Hashtable函数,时间函数,数据类型转换函数,DataTable函数,数学函数,脚本执行函数,JSON处理函数等几十个函数。详细请见首页说明
5、此脚本语言,不支持函数的定义,类的定义。可以通过脚本API函数来做函数的调用
6、问题反馈 Q扣 1060—151—476
以上是关于为自己的软件增加脚本编写功能并自定义API的主要内容,如果未能解决你的问题,请参考以下文章