首页 > Python基础教程 >
-
C#教程之C# 代码中调用 Javascript 代码段以提高应用
一般来说,我们需要在开发应用软件的配置文件中,添加一些参数,用于后续用户根据实际情况,自行调整。
配置参数,可以放在配置文件中、环境变量中、或数据库表中(如果使用了数据库的话)。通常,配置数据,以 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.