C# 代碼中調用 Javascript 代碼段以提高應用程序的配置靈活性(使用 Javascript .NET 與 Jint)


一般來說,我們需要在開發應用軟件的配置文件中,添加一些參數,用於后續用戶根據實際情況,自行調整。

配置參數,可以放在配置文件中、環境變量中、或數據庫表中(如果使用了數據庫的話)。通常,配置數據,以 key/value 的形式。

有時候,這種  key/value 的形式,不足以滿足用戶需求。比如,系統中有個定時刪除臨時文件的 job ,我們希望在客戶工廠的生產交接班期間及員工吃飯時間,比如客戶工廠生產交接班時間為 5:30 - 6:00 , 23:00-23:30, 中途吃飯時間為 11:00, 4:00。

也許,可以用正則表達式,來實現以上的功能。但實際情況一調查,我們發現,客戶用戶懂正則表達式的基本沒有,我們自己公司軟件開發人員懂正則表達式的也很少。如果做成正則表達式方式,后續代碼交接之后,能不能維護/修改,也很難說。

這樣,我們找到了"以 Javascript 的代碼段,進行判斷,作為配置參數值",這樣可以完美地解決我們的問題。Javascript 基本語法簡單,客戶用戶也可自行更改。

 

對於可在 C# 代碼中使用的 Javascript 引擎,我們找到了兩個:  Javascript .NET 與 Jint。前者依賴於 Goolge V8 引擎,運行時需要 Microsoft C Runtime Libraries, 后者則是純 C# 代碼組件。

為同時測試這兩種,我們先進行代碼抽象: 

Javascript 代碼,可能無 package/namespace ,可能無 function ,只是一段代碼。但無論如何,調用前賦值、調用程序、調用后獲取需要的數值,這個基本邏輯,是不會變的。

a. 基礎類定義如下:

 1 using System.Collections.Generic;
 2 
 3 namespace xxxx
 4 {
 5     public interface IJavascriptEngine
 6     {
 7         /// <summary>
 8         /// 執行一段 Javascript 代碼,傳入一些參數,得到一些數值
 9         /// </summary>
10         /// <param name="strJavascriptCode"></param>
11         /// <param name="inputParameters"></param>
12         /// <param name="outputNameValues">傳入時,只填key, 保留 value為空;返回時,填寫value</param>
13         void Execute(string strJavascriptCode, Dictionary<string, object> inputParameters, Dictionary<string, object> outputNameValues);
14     }
15 }

 

b. Javascript .NET 實現以上接口的代碼如下:

 1 using System.Collections.Generic;
 2 
 3 namespace dispatch_service.srv
 4 {
 5     public class JsNetJavascriptEngineSrv : IJavascriptEngine
 6     {
 7         public virtual void Execute(string strJavascriptCode, Dictionary<string, object> inputParameters, Dictionary<string, object> outputNameValues)
 8         {
 9             using (Noesis.Javascript.JavascriptContext context = new Noesis.Javascript.JavascriptContext())
10             {
11                 //step 1, 初始化各個變量值
12                 foreach (KeyValuePair<string, object> pair in inputParameters)
13                 {
14                     context.SetParameter(pair.Key, pair.Value);
15                 }
16 
17                 //step 2, 執行 Javascript 代碼,可能是多個函數,或無函數的代碼段
18                 context.Run(strJavascriptCode);
19 
20                 //step 3, 讀取所需的變量值,暫存到 nonNullKeyValues 變量中。
21                 Dictionary<string, object> nonNullKeyValues = new Dictionary<string, object>();
22                 foreach (KeyValuePair<string, object> pair in outputNameValues)
23                 {
24                     object value = context.GetParameter(pair.Key);
25                     if (value != null)
26                     {
27                         nonNullKeyValues[pair.Key] = value;
28                     }
29                 }
30 
31                 //step 4,將暫存的變量值,通過 outputNameValues 返回。
32                 foreach (KeyValuePair<string, object> pair in nonNullKeyValues)
33                 {
34                     outputNameValues[pair.Key] = pair.Value;
35                 }
36             }
37         }
38     }
39     
40 }

 

c. Jint 實現此接口的代碼如下:

 1 using System.Collections.Generic;
 2 using Jint;
 3 
 4 namespace xxxx
 5 {
 6     public class JintJavascriptEngineSrv : IJavascriptEngine
 7     {
 8         public virtual void Execute(string strJavascriptCode, Dictionary<string, object> inputParameters, Dictionary<string, object> outputNameValues)
 9         {
10             Engine en = new Engine();
11            
12             //step 1, 初始化各個變量值
13             foreach (KeyValuePair<string, object> pair in inputParameters)
14             {
15                 en.SetValue(pair.Key, pair.Value);
16             }
17                
18             //step 2, 執行 Javascript 代碼,可能是多個函數,或無函數的代碼段
19             en.Execute(strJavascriptCode);
20 
21             //step 3, 讀取所需的變量值,暫存到 nonNullKeyValues 變量中。
22             Dictionary<string, object> nonNullKeyValues = new Dictionary<string, object>();
23             foreach (KeyValuePair<string, object> pair in outputNameValues)
24             {
25                 Jint.Native.JsValue value = en.GetValue(pair.Key);
26                 if (value != null)
27                 {
28                     nonNullKeyValues[pair.Key] = value.ToObject();
29                 }
30             }
31 
32             //step 4,將暫存的變量值,通過 outputNameValues 返回。
33             foreach (KeyValuePair<string, object> pair in nonNullKeyValues)
34             {
35                 outputNameValues[pair.Key] = pair.Value;
36             }
37 
38         }
39     }
40 }

 

d. 最后,調用代碼里,可以自由切換以上兩種 Javascript 引擎:

 1                 Dictionary<string, object> inputParameters = new Dictionary<string, object>();
 2                 //給 inputParameters 填充數值,此處無需填充。
 3 
 4                 Dictionary<string, object> outputNameValues = new Dictionary<string, object>();
 5                 //給 outputNameValues 填充 key 值,此處需得到 canRunNow 變量數值。
 6                 outputNameValues["canRunNow"] = null;
 7 
 8             //IJavascriptEngine eng = new JsNetJavascriptEngineSrv();  9 IJavascriptEngine eng = new JintJavascriptEngineSrv(); 10 
11                 eng.Execute(jsStr, inputParameters, outputNameValues);
12                 object objValue = outputNameValues["canRunNow"];
13                 System.Nullable<bool> bValue =(System.Nullable<bool>) objValue;
14                 if (bValue != null && bValue.Value)
15                 {
16                     needRunNow = true;
17                 }

 

e. 附上 Javascript 代碼段:

var nowTime=new Date(); var canRunNow = false; var nowHour = nowTime.getHours();  var nowMin = nowTime.getMinutes();  if ( nowHour == 22 && nowMin == 0 ) {canRunNow = true;}

或:

var nowTime=new Date(); var canRunNow = false; var nowMin = nowTime.getMinutes(); var nowSec = nowTime.getSeconds(); if ( nowSec % 3 == 0 ) {canRunNow = true;}

這樣配置就很靈活了。

當然,這里的 Javascript 代碼段 , 作為配置參數 (key/value 中的 value),我們把它的多個代碼寫成一行。其實,不寫成一行,也是可行的。

 

-----------------------------------------------------------------------------------------------------------------------

轉發請注明出處。當心我晚上變大灰狼來摸你肚子喲。我是 jacklondon , at , cnblogs.com. 

開源項目 velocityweb 維護人。上海折桂軟件有限公司負責人。當前在開發及推廣折桂打印平台系統、折桂上傳平台系統。 http://zheguisoft.com ; http://www.cnblogs.com/jacklondon ;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM