在当今快速发展的商业环境中,企业经常需要根据市场变化和内部需求调整业务规则。为了应对这种需求,应用程序需要能够灵活地修改业务逻辑而无需重新编译代码。本文将介绍如何通过使用规则引擎实现这一目标。
在之前的工作中,所在的公司需要构建一个ETL(Extract, Transform, Load)系统,负责其中的“T”部分,即转换部分。在这个过程中,接触到了一个名为NxBRE的DLL库,它是一个开源的业务规则引擎。虽然对规则引擎并不是专家,但这个项目可能会对有所帮助。
将业务规则引擎(BRE)集成到应用程序中,可以提高编码和编写业务规则的智能性,从而加速应用程序的处理速度。然而,如果不当使用,它也可能会影响性能。
为了演示如何使用业务规则引擎,以下是一个使用VS 2010的小型演示项目,展示了如何根据员工的基本工资计算所得税和DA(Dearness Allowance,即生活补贴)的示例。
以下是一个包含规则的XBRE文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<xBusinessRules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="xBusinessRules.xsd">
<Decimal id="Tax" value="10"/>
<Decimal id="DAp" value="10"/>
<Decimal id="5000" value="5000"/>
<Decimal id="10000" value="10000"/>
<Decimal id="15000" value="15000"/>
<Decimal id="20000" value="20000"/>
<Decimal id="30000" value="30000"/>
<Decimal id="100000" value="100000"/>
<ObjectLookup id="EmpObj" objectId="EmpTexCal" member="BasicSalary"/>
<Logic>
<If>
<And>
<Between leftId="5000" rightId="10000" valueId="EmpObj">
</Between>
</And>
<Do>
<Modify id="Tax" type="Decimal" value="11.5"/>
</Do>
</If>
</Logic>
<Logic>
<If>
<And>
<Between leftId="5000" rightId="10000" valueId="EmpObj">
</Between>
</And>
<Do>
<Modify id="DAp" type="Decimal" value="25"/>
</Do>
</If>
</Logic>
<ObjectLookup id="ExpDAp" type="NxBRE.Imp.Util.Evaluator,NxBRE.Imp" member="CreateExpression">
<Argument value="("/>
<Argument valueId="EmpObj"/>
<Argument value="/"/>
<Argument value="100"/>
<Argument value=")"/>
<Argument value="*"/>
<Argument valueId="DAp"/>
</ObjectLookup>
</xBusinessRules>
以下是如何读取XBRE文件的示例代码:
public ReadRule(string RuleFilePath)
{
_FilePath = RuleFilePath;
StringBuilder sb = new StringBuilder(255);
if (GetShortPathName(_FilePath, sb, sb.Capacity) != 0)
{
_factory = new BREFactoryConsole(_engineTraceLevel, _ruleBaseTraceLevel).NewBRE(new XBusinessRulesFileDriver(sb.ToString()));
}
}
以下是如何设置特定对象的值的示例代码:
public void SetObjectRefrance(ReadRule objRule, string ObjectId, object Obj)
{
if (objRule.IsValidXML)
{
if (objRule.IsProcessed)
objRule.Reset();
objRule.Factory.RuleContext.SetObject(ObjectId, Obj);
}
}
以下是如何设置委托引用的示例代码:
public void SetDelegateRefrance(ReadRule objRule, string ObjectId, ExecuteRuleDelegate Delegate)
{
if (objRule.IsValidXML)
{
if (objRule.IsProcessed)
objRule.Reset();
objRule.Factory.RuleContext.SetFactory(ObjectId, new BRERuleFactory(Delegate));
}
}
以下是如何获取规则结果的示例代码:
public object GetRuleResult(ReadRule objRule, string ObjectId)
{
try
{
if (!objRule.IsProcessed)
objRule.ProcessRules();
return objRule.Factory.RuleContext.GetResult(ObjectId).Result;
}
catch (Exception)
{
}
return FlagResualt.NoProcessed;
}
以下是将上述功能整合在一起的综合函数示例代码:
public void EvaluateRule(ReadRule objRule, RuleRefrance[] RulesReferances, RuleDelegate[] RulesDelegates, RuleResualt[] RuleReply)
{
if (RulesReferances != null)
AddObjects(objRule, 0, RulesReferances);
if (RulesDelegates != null)
AddDelegates(objRule, 0, RulesDelegates);
// Process Rules
if (!objRule.IsProcessed)
objRule.ProcessRules();
//
if (RuleReply != null)
GetObjectResult(objRule, 0, RuleReply);
}