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. 基础类定义如下:
using System.Collections.Generic; namespace xxxx
{
public interface IJavascriptEngine
{
/// <summary>
/// 执行一段 Javascript 代码,传入一些参数,得到一些数值
/// </summary>
/// <param name="strJavascriptCode"></param>
/// <param name="inputParameters"></param>
/// <param name="outputNameValues">传入时,只填key, 保留 value为空;返回时,填写value</param>
void Execute(string strJavascriptCode, Dictionary<string, object> inputParameters, Dictionary<string, object> outputNameValues);
}
}
b. Javascript .NET 实现以上接口的代码如下:
using System.Collections.Generic; namespace dispatch_service.srv
{
public class JsNetJavascriptEngineSrv : IJavascriptEngine
{
public virtual void Execute(string strJavascriptCode, Dictionary<string, object> inputParameters, Dictionary<string, object> outputNameValues)
{
using (Noesis.Javascript.JavascriptContext context = new Noesis.Javascript.JavascriptContext())
{
//step 1, 初始化各个变量值
foreach (KeyValuePair<string, object> pair in inputParameters)
{
context.SetParameter(pair.Key, pair.Value);
} //step 2, 执行 Javascript 代码,可能是多个函数,或无函数的代码段
context.Run(strJavascriptCode); //step 3, 读取所需的变量值,暂存到 nonNullKeyValues 变量中。
Dictionary<string, object> nonNullKeyValues = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> pair in outputNameValues)
{
object value = context.GetParameter(pair.Key);
if (value != null)
{
nonNullKeyValues[pair.Key] = value;
}
} //step 4,将暂存的变量值,通过 outputNameValues 返回。
foreach (KeyValuePair<string, object> pair in nonNullKeyValues)
{
outputNameValues[pair.Key] = pair.Value;
}
}
}
} }
c. Jint 实现此接口的代码如下:
using System.Collections.Generic;
using Jint; namespace xxxx
{
public class JintJavascriptEngineSrv : IJavascriptEngine
{
public virtual void Execute(string strJavascriptCode, Dictionary<string, object> inputParameters, Dictionary<string, object> outputNameValues)
{
Engine en = new Engine(); //step 1, 初始化各个变量值
foreach (KeyValuePair<string, object> pair in inputParameters)
{
en.SetValue(pair.Key, pair.Value);
} //step 2, 执行 Javascript 代码,可能是多个函数,或无函数的代码段
en.Execute(strJavascriptCode); //step 3, 读取所需的变量值,暂存到 nonNullKeyValues 变量中。
Dictionary<string, object> nonNullKeyValues = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> pair in outputNameValues)
{
Jint.Native.JsValue value = en.GetValue(pair.Key);
if (value != null)
{
nonNullKeyValues[pair.Key] = value.ToObject();
}
} //step 4,将暂存的变量值,通过 outputNameValues 返回。
foreach (KeyValuePair<string, object> pair in nonNullKeyValues)
{
outputNameValues[pair.Key] = pair.Value;
} }
}
}
d. 最后,调用代码里,可以自由切换以上两种 Javascript 引擎:
Dictionary<string, object> inputParameters = new Dictionary<string, object>();
//给 inputParameters 填充数值,此处无需填充。 Dictionary<string, object> outputNameValues = new Dictionary<string, object>();
//给 outputNameValues 填充 key 值,此处需得到 canRunNow 变量数值。
outputNameValues["canRunNow"] = null; //IJavascriptEngine eng = new JsNetJavascriptEngineSrv();
IJavascriptEngine eng = new JintJavascriptEngineSrv();
eng.Execute(jsStr, inputParameters, outputNameValues);
object objValue = outputNameValues["canRunNow"];
System.Nullable<bool> bValue =(System.Nullable<bool>) objValue;
if (bValue != null && bValue.Value)
{
needRunNow = true;
}
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.
C# 代码中调用 Javascript 代码段以提高应用程序的配置灵活性(使用 Javascript .NET 与 Jint)的更多相关文章
- c代码中调用c++,c++代码中调用c代码
注意这里的c调用c++或者c++调用c的意思是.c文件中调用.cpp文件中的代码,或者相反 集成开发环境如vc++6.0或者vs都是通过文件后缀来区别当前要编译的是C代码还是C++代码,然后采用相应的 ...
- 如何在Java中调用Python代码
有时候,我们会碰到这样的问题:与A同学合作写代码,A同学只会写Python,而不会Java, 而你只会写Java并不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方设法“调 ...
- 在Java中调用Python代码
极少数时候,我们会碰到类似这样的问题:与A同学合作写代码, A同学只会写Python,不熟悉Java ,而你只会写Java不擅长Python,并且发现难以用Java来重写对方的代码,这时,就不得不想方 ...
- Android 在C代码中调用logcat
本文给<Android java传递int类型数组给C>中添加C代码中调用logcat的功能 Android.mk文件增加以下内容 LOCAL_LDLIBS += -llog C代码中增加 ...
- Dynamics AX 2012 R2 从代码中调用SSRS Report
平时,我们制作SSRS Report的方法主要有两种:使用Query或RDP.如果需要为报表传递参数,就要在代码中为报表参数赋值,然后在代码中调用报表.下面我总结下这两种报表在代码中传参和调用的方式: ...
- 在代码中调用 mvc 4 api
mvc 4 api 的调用有很多种,最常见也最简单的一种是 用 ajax 的方式在前端界面中调用, 如果是在后台代码中调用 ,是要复杂一些,以下是 以 post 的方式调用 api 的封装好的方法: ...
- 该对象尚未初始化。请确保在所有其他初始化代码后面的应用程序启动代码中调用 HttpConfiguration.EnsureInitialized()。
WebAPI使用属性路由,配置config.MapHttpAttributeRoutes();后出现错误: System.InvalidOperationException: 该对象尚未初始化.请确保 ...
- C#中调用PowerShell代码
在C#中调用PowerShell代码,很多时候Add是不好使的!要用AddScript!记录一下! using (Runspace runspace = RunspaceFactory.CreateR ...
- 在php代码中调用帝国cms头部变量temp.header的方法
在php代码中调用帝国cms头部变量temp.header的方法 代码如下: <?php require("../e/class/connect.php"); if(!def ...
随机推荐
- ASP.NET Core微服务+Tabler前端框架搭建个人博客1--开始前想说的话
写在前面 本人为在读研究生,特别喜欢.NET,觉得.NET的编程方式.语法都特别友好,学习.NET Core已经差不多有一年半了,从一开始不知道如何入门到现在终于可以编写一些小的应用程序,想一想还是非 ...
- asp.net core 2.0发布到IIS流程及报错解决方案
我这是个新装的服务器,没有安装任何软件. 一.发布流程 1.安装AspNetCoreModule托管模块,同时会自动安装..net core runtime DotNetCore.2.0.8-Wi ...
- mysql 开发进阶篇系列 46 物理备份与恢复( xtrabackup的 选项说明,增加备份用户,完全备份案例)
一. xtrabackup 选项说明 在操作xtrabackup备份与恢复之前,先看下该工具的选项,下面记录了xtrabackup二进制文件的部分命令行选项,后期把常用的选项在补上.点击查看xtrab ...
- 谷歌浏览器提示Adobe flash player不是最新版本的解决方法
版权声明:本文为博主原创文章,未经博主允许不得转载. 参考资料 https://jingyan.baidu.com/article/a3a3f811c3d5058da2eb8a39.html 如果电脑 ...
- No principal was found in the response from the CAS server
按网上的配置了 public String casServerUrlPrefix = "http://cas-server.com:8080/cas"; public String ...
- JwtBearer认证
ASP.NET Core 认证与授权[4]:JwtBearer认证 在现代Web应用程序中,通常会使用Web, WebApp, NativeApp等多种呈现方式,而后端也由以前的Razor渲染HT ...
- 浅谈Mybatis连接原理
众所周知数据库连接的过程,但是最近面试的人(菜面菜),都说用的SSM框架,但是我问了一下,mybatis是怎么连接上mysql的,基本上都会说:配置好的,直接用了,今天我来抛砖引玉一下,欢迎拍砖! 什 ...
- Linux文件系统及文件属性
一.Linux文件系统 1.穿件文件系统 Linux中当磁盘格式化创建文件系统时,会创建一定数量的节点索引Inode以及一定数量的块block,其中inode具有存储文件属性以及指向文件实体block ...
- python 闯关之路四(下)(并发编程与数据库编程)
并发编程重点: 并发编程:线程.进程.队列.IO多路模型 操作系统工作原理介绍.线程.进程演化史.特点.区别.互斥锁.信号. 事件.join.GIL.进程间通信.管道.队列. 生产者消息者模型.异步模 ...
- Python 通过 SMTP 发送邮件
Python版本:Python3.5.2 简介 SMTP是发送邮件的协议,Python 内置对 SMTP 的支持,可以发送纯文本邮件.HTML 邮件以及带附件的邮件. Python 对 SMTP 支持 ...