Calling Javascript snippets in C# code to improve application configuration flexibility (using Javascript. NET and Jint)

Keywords: C# Javascript Database

Generally speaking, we need to add some parameters in the configuration file of developing the application software for subsequent users to adjust themselves according to the actual situation.

Configuration parameters can be placed in configuration files, environment variables, or database tables (if a database is used). Usually, configure data in the form of key/value.

Sometimes, this form of key/value is not enough to meet the needs of users. For example, there is a job that deletes temporary files regularly in the system. We hope that during the production transition period of the customer factory and the meal time of the employees, such as the production transition time of the customer factory is 5:30-6:00, 23:00-23:30, and the meal time is 11:00 and 4:00.

Perhaps regular expressions can be used to achieve the above functions. However, a survey of the actual situation, we found that customers do not understand regular expressions, and software developers in our own company do not understand regular expressions. It is also difficult to say whether regular expressions can be maintained/modified after code handover.

In this way, we found the "Javascript code segment, judgment, as the configuration parameter value", which can solve our problem perfectly. The basic Javascript syntax is simple and can be changed by customers themselves.

 

For the Javascript engine that can be used in C# code, we found two: Javascript. NET and Jint. The former relies on the Goolge V8 engine, Microsoft C Runtime Libraries are needed at runtime, and the latter is a pure C code component.

To test both at the same time, we first abstract the code:

Javascript code, maybe no package/namespace, maybe no function, just a piece of code. However, in any case, the basic logic of assigning values before invocation, calling programs, and getting the required values after invocation will remain unchanged.

a. Basic classes are defined as follows:

 1 using System.Collections.Generic;
 2 
 3 namespace xxxx
 4 {
 5     public interface IJavascriptEngine
 6     {
 7         /// <summary>
 8         /// Execute a paragraph Javascript Code, pass in some parameters, get some values
 9         /// </summary>
10         /// <param name="strJavascriptCode"></param>
11         /// <param name="inputParameters"></param>
12         /// <param name="outputNameValues">When imported, only fill in key, Retain value When returning, fill in the blank. value</param>
13         void Execute(string strJavascriptCode, Dictionary<string, object> inputParameters, Dictionary<string, object> outputNameValues);
14     }
15 }

 

B. Javascript. NET implements the above interface code as follows:

 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, Initialize each variable value
12                 foreach (KeyValuePair<string, object> pair in inputParameters)
13                 {
14                     context.SetParameter(pair.Key, pair.Value);
15                 }
16 
17                 //step 2, implement Javascript Code, maybe multiple functions, or code snippets without functions
18                 context.Run(strJavascriptCode);
19 
20                 //step 3, Read the required variable values and save them to nonNullKeyValues Variable.
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,The temporary variable value is passed through outputNameValues Return.
32                 foreach (KeyValuePair<string, object> pair in nonNullKeyValues)
33                 {
34                     outputNameValues[pair.Key] = pair.Value;
35                 }
36             }
37         }
38     }
39     
40 }

 

c. Jint implements this interface with the following code:

 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, Initialize each variable value
13             foreach (KeyValuePair<string, object> pair in inputParameters)
14             {
15                 en.SetValue(pair.Key, pair.Value);
16             }
17                
18             //step 2, implement Javascript Code, maybe multiple functions, or code snippets without functions
19             en.Execute(strJavascriptCode);
20 
21             //step 3, Read the required variable values and save them to nonNullKeyValues Variable.
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,The temporary variable value is passed through outputNameValues Return.
33             foreach (KeyValuePair<string, object> pair in nonNullKeyValues)
34             {
35                 outputNameValues[pair.Key] = pair.Value;
36             }
37 
38         }
39     }
40 }

 

Finally, in the calling co d e, you can switch between the two Javascript engines freely:

 1                 Dictionary<string, object> inputParameters = new Dictionary<string, object>();
 2                 //to inputParameters Fill in the values. There is no need to fill in here.
 3 
 4                 Dictionary<string, object> outputNameValues = new Dictionary<string, object>();
 5                 //to outputNameValues Fill key Value, where you need to get canRunNow Variable values.
 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. Attach the Javascript code snippet:

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

Or:

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

The configuration is flexible.

Of course, the Javascript snippet here, as a configuration parameter (value in key/value), we write multiple lines of its code. In fact, it is feasible not to write in one line.

 

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

Please indicate the source for forwarding. Be careful that I get big gray wolf to touch your stomach at night. I'm jacklondon, at, cnblogs.com.

Open source project velocity web maintainer. Head of Shanghai Guigui Software Co., Ltd. At present, the development and promotion of Guigui printing platform system and Guigui upload platform system are under way. Http://zheguisoft.com; http://www.cnblogs.com/jacklondon;

Posted by mikeashfield on Wed, 19 Dec 2018 05:12:04 -0800