A2D规则引擎

写了个简单的规则引擎,普通情况够用了:

比如2家公司有各自的利率计算规则,如下:

在C#方面,没有写在C#的业务逻辑代码中,而是移到了外部规则文件中,如(ACompanyRatePolicy.r):

rule "Level 1"
when
alreadyCostPrice >= 0
alreadyCostPrice < 100
then
rate = 1
end
rule "Level 2"
when
alreadyCostPrice >= 100
alreadyCostPrice < 300
then
rate = 0.8
end
rule "Level 3"
when
alreadyCostPrice >= 300
then
rate = 0.5
end

不同的公司调用不同的Policy定义文件来执行逻辑:

核心调用代码:

public class CustomerRateService
{
public static decimal CalculateRate(decimal costedAlready, decimal priceThisTime, string rulePolicy)
{
using (RuleEngine engine = new RuleEngine(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Rules")))
{
engine.BindRule("Rating", rulePolicy); //此处的第一个参数"Rating"是规则组名称,对应的是物理文件夹,方便规则文件的管理和查看 engine.SetParameter("alreadyCostPrice", costedAlready);
engine.SetParameter("thisTimePrice", priceThisTime); engine.Process(); return engine.GetDecimal("rate");
}
} }

原理比较简单:

  1. 根据规则文件(.r文件)生成js代码
  2. 在C#中嵌入v8引擎执行这段js代码
  3. 获取结果

Make Things Move -- Javascript html5版(一)文件目录结构和工具方法准备

 

  从这一篇开始,就来开始我们的make things move之旅吧

  在此之前,要知道ActionScript(AS)的语法和JS是不一样的,AS是相对于JS而言更好的支持了面向对象的特性,所以我们可以自己实现一些简单的工具类,让我们更快速的构建我们的工程。不过我们不用全部实现AS中的东西,我们只用实现最基本的类的构造,类的继承和其他一些实用的工具函数就好了。

  其实我还想说的是,我们还是要实现AS的Sprite类和stage,因为这两个东西是实现AS动画最基本的元素,html5 canvas提供的js api还是比较低级的,我们可以简单的封装一下实现AS的sprite 和stage,不过这两个东西还是等后续讲有关动画的原理再来细说吧。另外,其实现在已经有很多开源的HTML5游戏框架,可以直接使用,而且已经很成熟社区也好,比如现在很火的cocos2d-html5,我不是很赞成自己造轮子写一个,不过如果是出于学习目的还是可以一试的,因为这样也比较容易理解框架底层的东西,和提高你的JS水平。话题跑远了……

  文件目录结构

  推荐模仿linux的文件结构吧,随便在哪放你的工程

   创建一个/mtm的文件夹,此文件夹的根目录下:
|-- index.html
|-- /css
|-- /js
|-- /bin 此目录旋转最终的用于执行的js文件
|-- /lib 放置库工具
|-- /etc 放置配置文件
|-- /mtm make things move 工程的主要例子的实现类

工具方法

  一在js/lib/目录下创建一个sys.js的文件

  然后实现我们的第一个构造类的工具方法:__class__。我写多了python,深受python类构造模式的影响(同样的我也不分号党,只有在写java或其他静态语言的时候),双下划线是表示系统内置属性或方法的意思,这只是我自己的习惯,读者可以根据自己的习惯来写,不过建议有一个好的规范,我的在JS里就不算是什么好的。读者也可自己实现一个可构造类并能实现继承的方法,我的实现如下:

// 参数不定,最后一个参数必须是实现的方法的json,前面的都是要继承的类
// opts中的__init__方法则为新类的构造函数
// example: var NewClass = __class__(Class1, Class2, {__init__: function () {}, }) this.__class__ = function (/*Class1, Class2,..., opts*/) {
var args = Array.prototype.slice.call(arguments),
opts
if (typeof args[args.length - 1] === 'function')
opts = {}
else
opts = args.pop()
var clss = opts.__init__ || function () {},
name = opts.__name__ || __filename__(__file__()) //获取当前js文件的名称作为这个类的类名,也可在opts中定义__name__
for (var i = 0, parent; parent = args[i]; i++)
__copy__(parent.prototype, clss.prototype)
__copy__(opts, clss.prototype)
clss.__name__ = clss.prototype.__name__ = name
return clss
}

  上面的方法中用到了几个新的工具方法:

1. __file__       获取当前文件路径

  2. __filename__   获取指定文件路径的文件名(已去掉后缀)

  3. __copy__             简单的拷贝属性的方法

  这些方法都在sys.js实现:

this.__copy__ = function (source, target) {
for (var k in source)
target[k] = source[k]
return target
} this.__file__ = function () {
var e = document.getElementsByTagName('script')
return e.length ? e[e.length - 1].src : ''
}

// 获取当前文件所在的目录
this.__dirname__ = function (s) {
var p = s.lastIndexOf('/')
if (p === 0)
return '/'
if (p === -1)
return ''
return s.slice(0, p)
}

// 获取指定文件路径的文件名字(带后缀)
this.__basename__ = function (s) {
var res = s.match(/\/([^\/]+\.\w+)$/i)
return res ? res[1] : ''
} this.__filename__ = function (s) {
var str = __basename__(s)
return str.length ? str.slice(0, str.lastIndexOf('.')) : str
}

  最后还有一个__load__方法,属于一个文件加载器,没办法js"还“没有import我们自己来实现一个

/**
* @param files {Array} 要加载的js文件的路径数组
* @param ok {Function} 加载完成后的回调
* @example: __load__(['js/sys.js'], function () {console.log('load done!')})
*/
this.__load__ = function () {
var _loaded_path = {}
var _loader = function (src, fnc) {
if (_loaded_path[src])
return fnc()
var s = document.createElement("script")
s.onload = function () {
_loaded_path[src] = 1
fnc()
}
s.onerror = function () {
throw "Error loading: " + src
}
s.src = src
document.body.appendChild(s)
}
return function (files, ok) {
files = files.slice()
if (files.length == 0)
return ok && ok()
_loader(files.shift(), function () {
__load__(files, ok)
})
}
}()

  把上面的代码都放到js/lib/sys.js文件中,就基本完成我们的的工具准备了,我们来试试使用上面的方法,顺便熟悉我们的文件 结构,在 js/mtm/   文件夹下创建一个Test.js文件,在这里我们用我们的工具函数创建我们的第一个类:

var Test = __class__({

    __init__: function () {
this.sayMyName()
}, sayMyName: function () {
alert("I am a Class, my name is " + this.__name__)
} })

再写一个继承类,和Test.js同目录下创建OtherTest.js(注意,我们的__class__方法是可以多重继续的,只是新类里没有可间接从自己类里调用父类的方法):

var OtherTest = __class__(Test, {

    __init__: function () {
// 手动调用父类的构造方法
Test.call(this)
}, sayMyName: function () {
// 手动调用父类的sayMyName方法
Test.prototype.sayMyName.call(this)
// 再弹出一个信息
alert("All done!")
} })

类是写完了,但我们并没有引用,我们来部署一下我们测试环境:在js/etc/ 目录下创建一个mtm_module.js的文件,里面把我们js/mtm/文件里的js路径都写入一个mtm_module数组中:

var mtm_module = [
'js/mtm/Test.js',
'js/mtm/OtherTest.js', ]

以后都把mtm文件的路径往这个数组里加。在js/lib/目录下创建一个main.js的最终执行文件,然后主要就是在这个文件中加载其他js 执行测试代码:

// 把js/mtm/里的测试类都加载进来
__load__(mtm_module, function () { // 实例化一个Test类
var test = new Test() })

最后就是写index.html页面,把主要的sys.js,mtm_module.js, main.js用标签引入就OK了:

<!doctype html>
<html>
<head>
<title> Make things move </title>
</head> <body>
<script src='js/lib/sys.js'></script>
<script src='js/etc/mtm_module.js'></script>
<script src='js/bin/main.js'></script>
</body>
</html>

  到此,如果过程都没有任何问题,你可以打开index.html    然后就会弹出我们上面写的信息!如果你用的是mac 或 linux系统建议直接用命令行工具在该工程根目录输入`python -m SimpleHTTPServer 8000` 然后浏览器上打开localhost:8000就能看到效果了。写了这么多,可能篇幅有些长,下次写看来要控制一下 :p

 
 

代码已经更新到A2D Framework了。

大家拿去用吧。。。哈哈。

自省推动进步,视野决定未来。
心怀远大理想。
为了家庭幸福而努力。
A2D科技,服务社会。
A2D Framework(Alpha)

  • 1. Cache System(本地缓存与分布式缓存共存、支持Memcache和Redis、支持贴标签形式(类似Spring 3.x的Cache形式))
  • 2. Event System(本地事件与分布式事件分发)
  • 3. IoC(自动匹配功能,实例数量限制功能)
  • 4. Sql Dispatcher System(基于Sql server的读写分离系统)
  • 5. Session System(分布式Session系统)
  • 6. 分布式Command Bus(MSMQ实现,解决4M限制,支持Session的读取)
  • 7. 规则引擎
 
分类: A2D Framework

A2D规则引擎的更多相关文章

  1. 抽取非基本验证到规则文件 - A2D规则引擎

    基本验证与业务验证,基本验证就是始终保持不变的验证规则,可以通过如下硬编码实现: public class Order { [Required] [Range(")] public deci ...

  2. 极其好用好学的规则引擎 - A2D规则引擎

    写了个简单的规则引擎,普通情况够用了: 比如2家公司有各自的利率计算规则,如下: 在C#方面,没有写在C#的业务逻辑代码中,而是移到了外部规则文件中,如(ACompanyRatePolicy.r): ...

  3. Scala化规则引擎

    1. 引言 什么是规则引擎 一个业务规则包含一组条件和在此条件下执行的操作,它们表示业务规则应用程序的一段业务逻辑.业务规则通常应该由业务分析人员和策略管理者开发和修改,但有些复杂的业务规则也可以由技 ...

  4. Asp.net 面向接口可扩展框架之业务规则引擎扩展组件

    随着面向接口可扩展框架的继续开发,有些功能开发出现了"瓶颈",有太多的东西要写死才好做.但写死的代码扩展性是非常的不好,迷茫中寻找出入... 进而想到我以前开发的好几个项目,都已有 ...

  5. Atitit.工作流 与 规则引擎

    Atitit.工作流 与 规则引擎 1.1. 应用来说,通常分为三部分:界面.业务逻辑和存储1 1.2. 自定义操作系列1 1.3. 自定义按钮系列2 1.1. 应用来说,通常分为三部分:界面.业务逻 ...

  6. 【java规则引擎】之Drools之Rete算法

    一:规则引擎--->规则引擎的核心是Pattern Matcher(模式匹配器).不管是正向推理还是反向推理,首先要解决一个模式匹配的问题.--->对于规则的模式匹配,可以定义为: 一个规 ...

  7. 规则引擎集成接口(七)规则引擎调用Java类

    规则引擎调用Java类 通过myEclipse编写一个简单工程,其中方法是两数相加等到结果,既结果1=输入值1+输入值2.实现规则调用外部接口的方法有三种. 1:接口实例:在myEclipse中制作一 ...

  8. node(规则引擎)

    本文主要记录node的下的一个开源规则引擎nools,给出简单的实例,github地址为: https://github.com/C2FO/nools 定义规则引擎(test.nools) defin ...

  9. 基于NXBRE规则引擎实现的柔性折扣策略

    规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策.接受数据输入,解释业务规则,并根据业务规则做出业务决策.应用背景 ...

随机推荐

  1. projecteuler----&gt;problem=19----Counting Sundays

    You are given the following information, but you may prefer to do some research for yourself. 1 Jan ...

  2. Android - View Alpha值

    Android - View Alpha值 本文地址: http://blog.csdn.net/caroline_wendy Alpha值主要控制图像的透明度(0-1),0代表透明.1代表不透明. ...

  3. my97 日期控件

    官网:http://www.my97.net/   好多广告啊! 文档地址: http://www.mysuc.com/test/My97DatePicker/

  4. cocos2d-x3.0之请求网络(phpserver)

    HelloWorldScene.h #ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos ...

  5. getch()和getchar()之再讨论

    原文:getch()和getchar()之再讨论 在C语言的字符处理函数中,getch()和getchar()是经常让人迷惑的两个函数,他们都有一些“奇怪的”特点让初学者摸不着头脑.两个函数有很多相似 ...

  6. 多线程学习之五超时模式Timer

    timed[超时模式]案例:一个线程提供下载数据,另一个线程执行下载,如果有5秒钟以上,提供下载的线程没有提供数据,下载线程因超时异常,停止下载线程运行. 超时异常类 /** * */ package ...

  7. 为Pythonic论坛添加一个“专题”功能

    代码还没读完就踏上了修改功能的深坑.还好思路清晰,通过修改模板和视图,实现了专题模块 原论坛的模式是用户点击节点发帖,然后就归到节点的分类里面了.我需要一个功能,就是右侧需要一个专题区,管理员发帖的话 ...

  8. 转载:Linux Used内存到底到哪里去了?

    转自:http://blogread.cn/it/article/6264?f=wb2 有时在Linux下会碰到这样的问题:ps aux看到的RSS内存只有不到30M,但是free看到内存却已经使用了 ...

  9. 使用c#给outlook添加任务、发送邮件

    原文:使用c#给outlook添加任务.发送邮件 c#在使用outlook提供的一些API时,需要将outlook相关的com引用到项目中. 具体方法就是用vs打开工程后,在工程上添加引用,在com选 ...

  10. weblogic启动报错--com.octetstring.vde.backend.BackendRoot

    错误现象: 使用bea用户启动weblogic时报错,错误信息如下: <2014-7-29 下午07时47分23秒 CST> <Notice> <Log Manageme ...