
適用版本: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這兩種方式可以利用腳本語言或編程語言自身的計算方法來方便地構建我們的表達式系統。