news 2026/7/6 20:35:05

AScript函数体系详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AScript函数体系详解

一、脚本内定义函数

脚本内定义函数,使得脚本配置更加灵活,不必依赖于硬编码增加函数。

标准定义

1 string s = @" 2 int sum(int a, int b) { 3 return a + b; 4 } 5 sum(3, 5); // 8 6 "; 7 var script = new Script(); 8 Assert.AreEqual(8, script.Eval(s));

简化定义(表达式体)

1 string s = @" 2 int sum(int a, int b) => a + b; 3 sum(3, 5); // 8 4 "; 5 var script = new Script(); 6 Assert.AreEqual(8, script.Eval(s));

匿名函数

函数名为“_”下划线。

1 string s = @" 2 var sum = int _(int a, int b) => a + b; 3 sum.Invoke(3, 5); // 8 4 "; 5 var script = new Script(); 6 Assert.AreEqual(8, script.Eval(s));

递归函数

1 string s = @" 2 int fib(int n) { 3 if (n <= 1) return n; 4 return fib(n - 1) + fib(n - 2); 5 } 6 fib(10); // 55 7 "; 8 var script = new Script(); 9 Assert.AreEqual(55, script.Eval(s));

函数重载

函数名相同,参数个数或参数类型不同。

1 string s = @" 2 int sum(int a, int b) => a + b; 3 int sum(int a, int b, int c) => a + b + c; 4 sum(3, 5) + sum(10, 20, 30); // 8 + 60=68 5 "; 6 var script = new Script(); 7 Assert.AreEqual(68, script.Eval(s));

二、注入外部函数

脚本上下文中注入函数

脚本上下文ScriptContext中提供了多个重载AddFunc/AddAction方法:

注入委托

1 var script = new Script(); 2 script.Context.AddFunc<int, int, int>("sum", (a, b) => a + b); 3 Assert.AreEqual(8, script.Eval("sum(3,5)"));

注入类静态方法

注入公开静态方法,不会注入泛型方法。

1 var script = new Script(); 2 script.Context.AddFunc<Math>(); 3 Assert.AreEqual(8, script.Eval("Abs(-8)")); // Math.Abs(-8)

注入类实例方法

注入公开实例方法,不会注入泛型方法。

1 var random = new System.Random(); 2 var script = new Script(); 3 // 注入所有公开实例方法 4 script.Context.AddFunc(random); 5 // 只注入Next方法,忽略其他方法 6 //script.Context.AddFunc(random, method => method.Name == "Next" ? method.Name : null); 7 Console.WriteLine(script.Eval("Next(1, 10)")); // random.Next(1, 10)

注入IFunctionEvaluator

实现IFunctionEvaluator可进行更细微的逻辑控制,非常适合实现参数数量、参数类型、返回值类型不固定的函数;同时如果实现IFunctionBuilder接口,可对函数编译进行控制,提高编译执行模式的性能。

内部的操作符就是实现IFunctionEvaluatorIFunctionBuilder来处理的。

示例:定义幂运算符**

1 /// <summary> 2 /// 幂运算:2**3=8 3 /// </summary> 4 public class PowerOperator : IFunctionEvaluator, IFunctionBuilder 5 { 6 public static readonly PowerOperator Instance = new PowerOperator(); 7 8 public void Build(FunctionBuildArgs e) 9 { 10 var left = e.Args[0].Build(e.BuildContext, e.ScriptContext, e.Options); 11 var right = e.Args[1].Build(e.BuildContext, e.ScriptContext, e.Options); 12 var v1 = Expression.Convert(left, typeof(double)); 13 var v2 = Expression.Convert(right, typeof(double)); 14 var v = Expression.Call(ExpressionUtils.Method_Math_Power, v1, v2); 15 var maxType = ScriptUtils.GetMaxType(left.Type, right.Type); 16 e.Result = Expression.Convert(v, maxType); 17 } 18 19 public void Eval(FunctionEvalArgs e) 20 { 21 if (e.Args.Count == 2) 22 { 23 var v1 = e.Args[0].Eval(e.Context, e.Options, e.Control, out _); 24 var v2 = e.Args[1].Eval(e.Context, e.Options, e.Control, out _); 25 var r = Math.Pow(Convert.ToDouble(v1), Convert.ToDouble(v2)); 26 var maxType = ScriptUtils.GetMaxType(v1.GetType(), v2.GetType()); 27 e.SetResult(ScriptUtils.Convert(r, maxType), maxType); 28 } 29 } 30 }

注入CustomFuncton

CustomFunction是由ITreeNode构造的函数,脚本中定义的函数就是解析成CustomFunction加到上下文环境中的。CustomFunction定义如下:

1 public class CustomFunction 2 { 3 public string Name { get; } 4 public string[] ArgNames { get; } 5 public Type[] ArgTypes { get; } 6 public Type ReturnType { get; } 7 public ITreeNode Body { get; } 8 9 public CustomFunction(string name, Type returnType, string[] argNames, Type[] argTypes, ITreeNode body); 10 11 public object Eval(ScriptContext context, BuildOptions options, EvalControl control, IList<ITreeNode> args, out Type returnType); 12 }

顶级上下文中注入函数

ScriptContext.Root顶级上下文中注入函数,可实现全局注入函数,并且所有脚本语言共享。

1 // 顶级上下文中注入函数 2 ScriptContext.Root.AddFunc<int, int, int>("sum", (a, b) => a + b); 3 4 // 直接调用sum函数 5 var script = new Script(); 6 Assert.AreEqual(8, script.Eval("sum(3,5)"));

脚本语言中注入函数

只在指定脚本语言中有效,其他脚本语言无法调用。

1 // C#脚本语言中注入函数 2 CSharpLang.Instance.AddFunc<int, int, int>("sum", (a, b) => a + b); 3 4 // 默认C#语言,可以直接调用sum函数 5 var script = new Script(); 6 // 如果指定其他语言,则报错sum函数不存在 7 // script.Context.Langs = new [] { "python3" }; 8 Assert.AreEqual(8, script.Eval("sum(3,5)"));

三、获取函数

只能从ScriptContext上下文中获取函数,如果当前上下文中不存在则从上级搜索,不会搜索ScriptLang中的函数。

1 string s = @" 2 int sum(int a, int b) => a + b; 3 sum(3, 5); // 8 4 "; 5 var script = new Script(); 6 Assert.AreEqual(8, script.Eval(s)); 7 var func = script.Context.GetFunc<int, int, int>("sum"); 8 Assert.AreEqual(30, func(10,20));

四、生成Lambda

动态脚本除了执行计算结果,还可以生成Lambda,该功能可用于将脚本转化为LINQ。

示例:将动态脚本条件语句转化为LINQ查询条件

1 var script = new Script(); 2 var whereCondition = script.Lambda<Person, bool>("p.Name=='tom' || p.Name=='jim'", "p"); 3 IQueryable<Person> query = ...; 4 // query.Where(p => p.Name=="tom" || p.Name=="jim") 5 var list = query.Where(whereCondition).ToList();

五、生成委托

将脚本编译生成委托,然后在程序调用执行,也是一个常用场景。

1 var script = new Script(); 2 var sum = script.Compile<int, int, int>("a+b", "a", "b"); 3 Assert.AreEqual(8, sum(3, 5));
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 20:29:52

端口复用技术:红队视角下的隐蔽通信与实战指南

端口复用技术&#xff1a;红队视角下的隐蔽通信与实战指南在服务器不出网、流量被严格审计的场景下&#xff0c;传统反弹 Shell 方案&#xff08;如 frp、Cobalt Strike Beacon&#xff09;往往因特征明显而被拦截。端口复用技术通过"寄生"于合法服务端口之上&#x…

作者头像 李华
网站建设 2026/7/6 20:27:18

题解:学而思编程 解密

【题目来源】 学而思编程:解密 【题目描述】 上一次,小猴的加密方式很快就被破解掉了,后来他学习了一个很经典的加密方式——“凯撒密码”,可是他觉得这个也很容易就会被别人破解,所以他决定创造一种“猴氏撒密码”。 和“凯撒密码”一样,“猴氏撒密码撒密码”也是利…

作者头像 李华
网站建设 2026/7/6 20:25:50

SDC命令详解:使用get_ports命令进行查询

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 指定静默 指定使用正则表达式 指定精确匹配 指定大小写不敏感 指定过滤 指定patterns参数 指定设计对象 Multicorner-Multimode支持 写在最后 get_ports命令…

作者头像 李华
网站建设 2026/7/6 20:24:35

MC6470与PIC18LF46K80的6DOF姿态控制实现

1. MC6470与PIC18LF46K80的硬件协同架构MC6470作为一款6自由度惯性测量单元(6DOF IMU)&#xff0c;其核心价值在于集成了三轴加速度计和三轴陀螺仪。在实际项目中&#xff0c;这颗芯片的独特之处在于其内置的传感器数据融合算法&#xff0c;能够直接输出姿态角数据&#xff08;…

作者头像 李华
网站建设 2026/7/6 20:23:47

Encog遗传算法深度解析:如何优化复杂问题的解决方案

Encog遗传算法深度解析&#xff1a;如何优化复杂问题的解决方案 【免费下载链接】encog-java-core 项目地址: https://gitcode.com/gh_mirrors/en/encog-java-core Encog是一个强大的机器学习框架&#xff0c;其中的遗传算法模块为解决复杂优化问题提供了高效途径。遗传…

作者头像 李华
网站建设 2026/7/6 20:20:56

HokoBlur源码深度剖析:Box、Gaussian与Stack模糊算法实现原理

HokoBlur源码深度剖析&#xff1a;Box、Gaussian与Stack模糊算法实现原理 【免费下载链接】HokoBlur an easy-to-use blur library for Android, support efficient dynamic blur tasks. 项目地址: https://gitcode.com/gh_mirrors/ho/HokoBlur HokoBlur是一个专为Andro…

作者头像 李华