65.9K
CodeProject 正在变化。 阅读更多。
Home

NxBRE( 规则引擎) 的基本帮助

2012年6月16日

CPOL

1分钟阅读

viewsIcon

73568

downloadIcon

2406

这里是 NxBRE( 规则引擎) 用于基本业务规则的帮助

引言

在本文中,我们将探讨如何在不重新编译代码的情况下,将动态业务规则应用于应用程序。

背景

我的公司需要构建一个 ETL,我的职责是负责“T”部分。

你可以在这里找到关于 NxBRE DLL 的简要介绍:http://sourceforge.net/projects/nxbre/。正如我所说,我不是规则引擎方面的专家,但这个项目可能会帮助你。

在你的应用程序中实现 BRE 是一件好事,你将代码和编写业务规则的智慧将加速你的应用程序,否则可能会影响性能。

使用代码 

你需要 VS 2010,这个项目将向你展示一个关于员工税收和 DA 计算的简单演示,具体取决于他们的基本工资。这是包含规则的 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"/>
  
  <!-- Calculation Of Tax -->
  
  <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>
    <ElseIf>
      <And>
        <Between leftId ="10000" rightId ="15000" 
                  valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="Tax" type="Decimal" value ="13.5"/>
      </Do>
    </ElseIf>
    <ElseIf>
      <And>
        <Between leftId ="15000" rightId ="20000" 
                    valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="Tax" type="Decimal" value ="14.5"/>
      </Do>
    </ElseIf>
    <ElseIf>
      <And>
        <Between leftId ="20000" rightId ="30000" 
                      valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="Tax" type="Decimal" value ="15.5"/>
      </Do>
    </ElseIf>
    <ElseIf>
      <And>
        <Between leftId ="30000" rightId ="100000" 
                    valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="Tax" type="Decimal" value ="17"/>
      </Do>
    </ElseIf>
  </Logic>
 
  <!-- <ObjectLookup id ="EmpObjOut" 
               objectId ="EmpTexCal" member ="TaxPercentage">
    <Argument valueId="Tax"/>
 </ObjectLookup> -->
  <!-- Calculation Of DA -->
  <Logic>
    <If>
      <And>
        <Between leftId ="5000" rightId ="10000" valueId ="EmpObj">
        </Between>
      </And>
      <Do>
        <Modify id ="DAp" type="Decimal" value ="25"/>
      </Do>
    </If>
    <ElseIf>
      <And>
        <Between leftId ="10000" rightId ="15000" valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="DAp" type="Decimal" value ="30"/>
      </Do>
    </ElseIf>
    <ElseIf>
      <And>
        <Between leftId ="15000" rightId ="20000" valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="DAp" type="Decimal" value ="40"/>
      </Do>
    </ElseIf>
    <ElseIf>
      <And>
        <Between leftId ="20000" rightId ="30000" valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="DAp" type="Decimal" value ="50"/>
      </Do>
    </ElseIf>
    <ElseIf>
      <And>
        <Between leftId ="30000" rightId ="100000" valueId ="EmpObj" excludeLeft ="true">
        </Between>
      </And>
      <Do>
        <Modify id ="DAp" type="Decimal" value ="60"/>
      </Do>
    </ElseIf>
  </Logic>
  <!-- Example Of Evaluation -->
  <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>
  <ObjectLookup id="EvalDAp"	type="NxBRE.Util.Compilation" member="Evaluate">
    <Argument valueId="ExpDAp" />
  </ObjectLookup>
  <ObjectLookup id="CastDAp"	type="NxBRE.Imp.Util.Casting,NxBRE.Imp" member="CastData">
    <Argument valueId="EvalDAp" />
    <Argument value="System.Decimal" />
  </ObjectLookup>
  <ObjectLookup id ="EmpObjOut" objectId ="EmpTexCal" member ="DA">
    <Argument valueId="CastDAp"/>
  </ObjectLookup>
</xBusinessRules> 

以下是如何读取 XBRE 文件,我稍后会解释 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);
    }
}

我们可以设置任何类型的 ExecuteRuleDelegate 委托,通过它可以我们在执行规则时回调我们的基础代码。

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);

}

GetObjectResult 只是使用反射在我们的 ORM 或任何其他类中设置值。

现在如何调用所有这些并获取规则输出,这非常简单

© . All rights reserved.