为自己的软件增加脚本编写功能并自定义API
Posted 足球中国
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为自己的软件增加脚本编写功能并自定义API相关的知识,希望对你有一定的参考价值。
CBScript语法介绍
开发背景:为ERP系统统计报表提供用户定义的公式,生成复杂的数据及表格内容。做一定的二次开发。
为什么不使用动态编译:因为有些函数需要在服务器端执行,执行时有安全风险,比如错误或者有意的编程,删除服务器的文件
[下载地址]
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
自定义API有两种方式:
3.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;
}
3.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函数来做函数的调用
以上是关于为自己的软件增加脚本编写功能并自定义API的主要内容,如果未能解决你的问题,请参考以下文章