适用版本:NX6以上
本技巧主要讨论如何使用VSA和CodeCompiler来开发表达式系统。
(资料图片)
应用环境正如之前提到的,有的情况客户需要在字符串表达式中定义一些运算,需要我们的程序解析并计算出结果。除了手动编写表达式系统和借用NX的表达式功能两种方法外,我们还可以通过VSA和CodeCompiler来开发我们自己的表达式系统。
图1
通过VSA引擎调用JavaScript的Eval()函数JavaScript(简称“JS”) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名,但是它也被用到了很多非浏览器环境中,JavaScript 基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。
由于JavaScript具有简单易学、应用广泛等特点,很适合被应用程序用作内嵌脚本的脚本语言。对于本课题的表达式系统开发,JavaScript中有Eval()函数,可以计算输入字符串的值。表达式中可以调用JavaScript中的其他函数,例如数学函数。输入的字符串甚至可以是一段完整的JS代码。
以下JS脚本将计算字符串表达式的值并打印结果(网页):
图2
图3
VSA(全称Visual Studio for Applications)是一种允许.NET开发者在自己的应用程序中管理和编译VB脚本、JS脚本等脚本语言的技术。通过这个技术,即使程序已经编译,用户也可以根据自己的需要对程序进行定制。虽然VSA已经在visual studio 2005后的版本被标记为过时,并且没有可用的替代方法,但是我们依然能使用它。
将上面的JS脚本用VSA和C#改写:
图4
通过CodeCompiler动态编译表达式System.CodeDom.Compiler 命名空间定义某些类型,用于从 CodeDOM 图中生成源代码,并管理使用支持语言的源代码的编译工作。编译器供应商或开发人员可以扩展支持语言。
.NET Framework 包括适用于 CSharpCodeProvider、JScriptCodeProvider 和 VBCodeProvider 的代码生成器和代码编译器。
我们可以对将用户的表达式看作是一段简单的C#代码,通过.NET提供的代码编译器将用户输入的表达式嵌入到代码模板中,编译后通过反射动态加载程序集并获取结果。
首先提供代码模板:
图5
可以注意到代码中有注释内容:“/*Replace exp*/”,获取代码模板后此处将被替换为用户输入的表达式后进行编译。
代码模板可以保存在代码文件xx.cs中,读取成文本、替换表达式后编译。在本例中代码文件被内嵌到DLL中并读取为文本。
图6
图7
此方法的好处在于代码和表达式有较统一的代码语法规范。通过在代码模板中定义新的方法,可以为用户提供更多的自定义函数。例如将以下代码添加到模板中可以添加平方计算的函数:
public static double Sq(double val) => val * val;
上例中的表达式可以修改为:Math.Sqrt(Sq(3) + Sq(4))。
但是此方法的缺点也很明显,实际上每一次调用都需要进行编译生成程序集,并加载新的程序集,因此速度较慢且会消耗很多内存。
总 结
对于一些需要在配置文件和数据表中写入表达式并由我们程序获取计算的需求,我们通过VSA和CodeCompiler这两种方式可以利用脚本语言或编程语言自身的计算方法来方便地构建我们的表达式系统。