为自己的软件增加脚本编写功能并自定义API

Posted 足球中国

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为自己的软件增加脚本编写功能并自定义API相关的知识,希望对你有一定的参考价值。

CBScript语法介绍

开发背景:为ERP系统统计报表提供用户定义的公式,生成复杂的数据及表格内容。做一定的二次开发。

为什么不使用动态编译:因为有些函数需要在服务器端执行,执行时有安全风险,比如错误或者有意的编程,删除服务器的文件

 下载地址 提取码 2973

使用方法 项目添加引用 [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的主要内容,如果未能解决你的问题,请参考以下文章

为自己的软件增加脚本编写功能并自定义API

Xilica添加Lua脚本

API管理工具之Postman脚本编写

ODPS Spark PySpark分组排序打序号并自关联(包含中文乱码问题解决)

Auth0 端点 API 的自定义实现?

高德地图进行浏览器定位并自定义定位按钮