返回首页

简介
作为尚未,我一直无法找到一个合适的规则引擎使用在我的。NET项目。当然,也有ILOG和BizTalk有这样大的家伙已经完全成熟的规则引擎。但是,我需要的东西简单和自由,我可以到我的。NET应用程序中嵌入。
。NET 3.0中引入的Windows Workflow Foundation,其中有一个以规则为基础的活动。当你到一个工作流程中的某一点,你可以运行在对象上的一些规则,并用它来改变对象和/或决定该走的路旁边的工作流程。基本上,工作流,可以不存在没有某种规则。袭击约我本实施细则的是,它使用的条件和行动的CodeDOM。最近,我写了一个{A}],使我的CodeDOM的编程生活变得更轻松。那么,为什么不把解析器来的?
我应该提到的前期,这决不是一个真正的规则引擎。 NET 3.0中的规则,采用正向链,这意味着还有很多,你没有做。但是,前进链不能跨类型。这个工作是在以后的文章中的主题。演示
示范如何将本规则引擎的工作原理,可以在以下链接找到。这是一个小游戏,我来说明如何可以在应用程序中使用DmRules:]。目标
我需要我的嵌入规则引擎能够处理某些事情。为了澄清:虽然我与Prolog的方式在高校的实验,我有没有兴趣,这里在实施。我更感兴趣的是获得一个核心功能集,是在商业​​应用中对我有用。此外,它是我的信念,业务分析师,不知道如何编写不应该尝试编写规则。所以,我不会尝试作出的规则写很容易,他们这样做!下面是一些我希望我的规则库做的事情:处理计算 - 当您更新数量在一个对象的某个地方,任何其他对象使用,这个数字在计算应重新评估。例如,我有一个类,计算出多少钱,我需要在我的每月预算分配。计算的部分是对天然气的预算。另一个对象,目前天然气价格。 ,价格变动时,我每月总预算的数量应该改变以及。气价的对象不应该依赖于它的对象,应自动更新。断言/审计 - 当值超出可接受的范围内,你可能想作出回应。你可以提出一些错误标志,或者到一个日志记录的问题。正向链 - 如上所述,如果在一个对象改变,应重新评估A,则对象B,对象B,对象取决于。基本上,该系统应能够应对变化没有明确告诉它更新的编码。非侵入性 - 实际代码的变化,以方便规则应该是微不足道的。配置简单 - 我想有一个非常大的,丑陋的XML文件定义的规则,以避免。一个没有规则引擎的培训初级程序员应该能够阅读和理解从XML配置规则。适应变化 - 让我们面对它,也有其他的方式来处理计算,并断言和审计。面向方面的编程或只需使用。NET的事件等技术都相当足够。但是,真正重要的是能够改变的规则是如何工作的。规则执行的条件,计算,或行动可能会改变。规则引擎使您能够处理这些变化。一个在Windows Workflow Foundation入门规则
让我们看看运行规则的一个例子。微软已经提供了一个基本的规则编辑器,让你写的条件和行动,而不是使用CodeDom中的GUI。使用该工具,而是我们将自己写的CodeDOM。
在这里我们的例子中类:

public class Class1

{

   private int _Foo;

   private string _Bar;



   public int Foo

   {

      get { return _Foo; }

      set { _Foo = value; }

   }



   public string Bar

   {

      get { return _Bar; }

      set { _Bar = value; }

   }

}

现在,我们可以写一个类到Class1的适用规则。首先,我们必须包括正确的引用。 System.Workflow.Activities和System.Workflow.ComponentModel您的项目中添加引用。现在,我们将通过代码一步一步走。我们不需要太多的命名空间包括:{C}
,我们正在使用的核心类是所谓的规则集。使用微软的工具时,这个对象是序列化的规则文件。
RuleSet rs = new RuleSet();

Rule r = new Rule("Rule A");

rs.Rules.Add(r);

WF中的规则有一个条件,一组动作来执行,如果条件为真,和一组动作来执行,如果条件为假。所有这些,都写在CodeDom中。我们要测试的条件是,如果物业美孚等于3。
CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression();

CodePropertyReferenceExpression fooRef = new 

   CodePropertyReferenceExpression(thisRef, "Foo");

CodeBinaryOperatorExpression fooCond = new CodeBinaryOperatorExpression();

fooCond.Left = fooRef;

fooCond.Operator = CodeBinaryOperatorType.ValueEquality;

fooCond.Right = new CodePrimitiveExpression(3);

正如你可以看到,我没有使用我的CodeDOM表达式解析器库。这将留待以后。不管怎么说,我们采取我们的表达和运用规则条件。
r.Condition = new RuleExpressionCondition(fooCond);

现在,我们需要一个要执行的动作,至少表明规则的工作:
CodePropertyReferenceExpression barRef = new 

   CodePropertyReferenceExpression(thisRef, "Bar");

CodeAssignStatement barThen = new CodeAssignStatement();

barThen.Left = barRef;

barThen.Right = new CodePrimitiveExpression("Gotcha");

这将改变值栏quot; Gotchaquot;只要条件为真。我们只需要添加它作为一个quot; thenquot,行动:
现在,我们要申请一个验证我们的规则。验证器基地本身的一种类型。基本上,它是要验证你的规则上使用Class1的有效属性/方法。这也使我想起一个有趣的讨论点。规则集是一套规则适用于一种类型的时间。它非常有意义,为什么它是这样,但它确实向前链等,也有要处理的,为了有一个有用的规则引擎施加的限制。
RuleValidation rv = new RuleValidation(typeof(Class1), null);

rs.Validate(rv);

现在,我们要执行的规则。为了测试规则的正常工作,我们将在增加foo的值,直到它击中3循环,然后检查酒吧的价值:
Class1 c = new Class1();

c.Bar = "Uh-uh";



for (int i = 0; i < 4; i++)

{

   c.Foo = i;

   RuleExecution rexec = new RuleExecution(rv, c);

   rs.Execute(rexec);

   Console.WriteLine("i: " + i + "\n\tFoo: " + c.Foo + "\n\tBar: " + c.Bar);

}

输出结果:
i: 0

    Foo: 0

    Bar: Uh-uh

i: 1

    Foo: 1

    Bar: Uh-uh

i: 2

    Foo: 2

    Bar: Uh-uh

i: 3

    Foo: 3

    Bar: Gotcha

这个测试是包含在源代码包,这样你就可以看到自己。你绝对可以看到,该系统具有一定的潜力。但是,除非我们要结婚了微软的规则书写工具,我们将不得不想出一个办法来处理与CodeDom中。输入我的CodeDOM表达式解析器。DmCodeDom - CodeDom中助手库
像我表明一个表达式解析器],是不够的处理规则,因为它不处理报表在所有。所以,我介绍了另一个小帮手库帮我写报表。这个辅助库只涵盖的基础知识:转让宣言IF / ELSE - 不允许在WF规则河套 - WF规则也不允许表达式语句
为了说明,以下简单的循环,所有上述要素:
for (int i = 0; i < 7; i++)

{

   if (i % 2 == 1)

      foo.Bar();

}

在这里,你将如何把它写在CodeDom中:
CodeIterationStatement cis = new CodeIterationStatement();

CodeVariableReferenceExpression refI = new 

   CodeVariableReferenceExpression("i");

cis.InitStatement = new CodeVariableDeclarationStatement(

   typeof(int), "i", new CodePrimitiveExpression(0));

cis.IncrementStatement = new CodeAssignStatement(refI, 

   new CodeBinaryOperatorExpression(refI, 

   CodeBinaryOperatorType.Add,

   new CodePrimitiveExpression(1)));

cis.TestExpression = new CodeBinaryOperatorExpression(refI, 

   CodeBinaryOperatorType.LessThan, 

   new CodePrimitiveExpression(7));

CodeConditionStatement ccs = new CodeConditionStatement();

ccs.Condition = new 

   CodeBinaryOperatorExpression(new 

      CodeBinaryOperatorExpression(refI, 

         CodeBinaryOperatorType.Modulus,

         new CodePrimitiveExpression(2)),

      CodeBinaryOperatorType.ValueEquality,

      new CodePrimitiveExpression(1));

CodeMethodInvokeExpression cmie = new 

   CodeMethodInvokeExpression(new 

      CodeVariableReferenceExpression("foo"), "Bar", 

      new CodeExpression[0]);

ccs.TrueStatements.Add(cmie);

cis.Statements.Add(ccs);

唷! CodeDom中可以得到丑陋的快速。 ,这是一个简单的循环。我们真的这样做。下面是我做我的助手类的确切相同的循环:
ForLoop fl = new ForLoop();

fl.InitStmt = new Declaration("int", "i", "0");

fl.IncrStmt = new Assignment("i", "i + 1");

fl.Cond = "i < 7";

IfElse ie = new IfElse();

ie.Cond = "i % 2 == 1";

ie.TrueStmts.Add(new ExprStmt("foo.Bar()"));

fl.LoopStmts.Add(ie);

我之所以选择像ForLoop和分配使用的类,因为我希望能够通过XmlSerializer类序列化到XML。下面是上面的循环看起来像什么,如果序列化到XML:
<DmCdStmt 

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 

   xsi:type="ForLoop" cond="i < 7">

   <InitStmt xsi:type="Declaration" type="int" varName="i" initExp="0" />

   <IncrStmt xsi:type="Assignment" left="i"

      right="i + 1" />

   <LoopStmts>

      <DmCdStmt xsi:type="IfElse" cond="i % 2 == 1">

         <TrueStmts>

            <DmCdStmt xsi:type="ExprStmt" expr="foo.Bar()" />

         </TrueStmts>

         <FalseStmts />

      </DmCdStmt>

   </LoopStmts>

</DmCdStmt>

我很高兴。NET 2.0中,他们终于固定XmlSerializer的,这样它可以让你来序列化和反序列化,而不是只具体类的抽象基类。的XML可能会有点简单,但将采取实施作IXmlSerializable,做我自己的努力实在是不值得的收益。
有一天,我实际上可能变成一个严重的CodeDOM帮手库DmCodeDom。如果你有兴趣,后在这篇文章的底部(或给我投票的5 {S0})发表评论。使用代码
显示此代码是如何工作的最好的办法是用一个例子。我有两个简单的类:Order和OrderItem的。每个订单项目的集合。为了有一个总的汇总所有项目的成本。我要处理的有两种情况:项目是从订单中删除,并一个项目的价格或数量的改变而改变。
下面是Order类:
public class Order {

   private List<OrderItem> _Items = new List<OrderItem>();

   private int _NumItems = 0;

   private float _Total = 0f;

   public List<orderitem> Items {

      get { return _Items; }

   }

   public int NumItems {

      get { return _NumItems; }

   }

   public float Total {

      get { return _Total; }

   }

   internal void RecalculateTotal() {

      _Total = 0f;

      foreach (OrderItem oi in _Items)

         _Total += oi.Price * oi.Units;

   }

   public Order() {}

   public OrderItem NewItem() {

      return new OrderItem(this);

   }

   public OrderItem NewItem(float price, int units) {

      return new OrderItem(price, units, this);

   }

}</orderitem>

一个非常简单的的类,你可以看到。它有一个项目清单,并报告了订单的总成本。注意这里的一件事是,有一个项目数的属性不返回Items.Count。这样做的目的,使规则能识别一个项目的是添加或删除。当然,还有其他方法可以做到这一点,但我选择了这个方法。
你可能想象的OrderItem是什么样子。下面是这个类:
public class OrderItem : BaseObject {

   private float _Price = 0f;

   private int _Units = 0;



   private Order _Order = null;

   public float Price {

      get { return _Price; }

      set {

         if (value != _Price) {

            _Price = value; 

            MarkDirty();

         }

      }

   }

   public int Units {

      get { return _Units; }

      set { 

         if (value != _Units) {

            _Units = value;

            MarkDirty();

         }

      }

   }

   public Order Order {

      get { return _Order; }

   }

   internal OrderItem(Order order) {

      _Order = order;

   }

   internal OrderItem(float price, int units, Order order) {

      _Price = price;

      _Units = units;

      _Order = order;

   }

}

有几件事情要注意这个类。被标记为内部的构造,因为我希望他们能够创建Order类。单位或价格的变化将标记为脏的对象。如果你从来没见过此之前,它基本上信号,被改变的对象。这是不够好,通知他们重新评估的规则。 CSLA使用这种技术,认识到需要更改保存到数据库中。肮脏的标志是包含在BaseObject类,它看起来像这样:
public abstract class BaseObject {

   protected bool _IsDirty = false;

   public bool IsDirty {

      get { return _IsDirty; }

   }        

   public void MarkDirty() {

      _IsDirty = true;

   }

}
创建和运行规则
我们写的第一条规则是要处理的项目数的变化。此规则应用于Order类。我们将手写整个事情,然后我会告诉以后如何你可以把应用程序配置的规则。首先,让我们的设置规则:
DmRule dr = new DmRule("this.NumItems != this.Items.Count",

   "Rule1",

   new DmCdStmt[] { 

      new ExprStmt("this.RecalculateTotal()"),

      new Assignment("this._NumItems", "this.Items.Count"),

      },

   new DmCdStmt[0]

   );

Parser parser = new Parser();

parser.Fields.Add("_NumItems");

DmRuleSet drs = new DmRuleSet();

drs.RuleTypes.Add(new DmRuleTypeSet(typeof(Order), new DmRule[] { dr }));

drs.Eval(parser);

因此,我们创建一个DmRule对象,以表示我们的规则。规则的条件是比较的项目数与该Items.Count属性。如果他们不匹配,那么一个项目中添加或删除。如果规则的计算结果为true时,会发生两件事:重新计算,总项目数是改变,以反映目前的项目数量。我宁愿重新计算规则的动作总,但规则库不允许CodeIterationStatements。
创建规则后,我们与之相匹配的一个类型,并添加DmRuleSet将处理规则执行。您可能还注意到,该表达式解析器需要知道,_NumItems是一个领域。
我们要做的是创建一个订单,然后给它添加一个项目。当我们运行的规则,它应该弄清楚,增加了一个项目,并重新计算总。
输出结果是:
Before:

  NumItems: 0

  Total: 0

After:

  NumItems: 1

  Total: 4.6
使用RuleExec简化一切
在库中包含的是一个静态类称为RuleExec。这个类需要自动为您照顾一些事情:规则可以指定应用程序的配置,而不​​是手动创建。通过检查类型字段自动添加到表达式解析器。一个对象的运行规则,可以在一行代码。
这部分,我们将添加另一个规则。此规则适用于OrderItem的类。当一个变化是,无论是单位或单位数量的价格,该项目将被标记为脏。当发生这种情况,我们要重新计算订单总额。我们将添加此规则Order类的现有规则,并把整个事情在App.config:
<configuration>

   <configSections>

      <section 

         name="dmRulesConfig" 

         type="DmRules.Configuration.DmRulesConfigHandler, DmRules" 

         />

   </configSections>



   <dmRulesConfig>

   <DmRuleSet 

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

      xmlns:xsd="http://www.w3.org/2001/XMLSchema">

      <RuleTypes>

         <DmRuleTypeSet type="DmRules.TestHarness.Order, DmRules.TestHarness">

            <Rules>

               <DmRule cond="this.NumItems != this.Items.Count" name="Rule1">

                  <ThenStmts>

                     <DmCdStmt xsi:type="ExprStmt" expr="this.RecalculateTotal()" />

                     <DmCdStmt xsi:type="Assignment" left="this._NumItems" 



                        right="this.Items.Count" />

                  </ThenStmts>

                  <ElseStmts />

               </DmRule>

            </Rules>

         </DmRuleTypeSet>

         <DmRuleTypeSet type="DmRules.TestHarness.OrderItem, DmRules.TestHarness">

            <Rules>

               <DmRule cond="this.IsDirty" name="Rule1">

                  <ThenStmts>

                     <DmCdStmt xsi:type="ExprStmt" 

                        expr="this.Order.RecalculateTotal()" />

                     <DmCdStmt xsi:type="Assignment" left="this._IsDirty" 

                        right="false" />

                  </ThenStmts>

                  <ElseStmts />

               </DmRule>

            </Rules>

         </DmRuleTypeSet>

      </RuleTypes>

   </DmRuleSet>

   </dmRulesConfig>



</configuration>

从这个例子,你应该能够看到如何将XML格式化。如果你经常使用XmlSerializer,那么这应该很熟悉。 OrderItem的规则将检查的对象是标记为脏。如果是这样的话,它告诉家长为了重新计算其总量,并改变脏标志回false。还要注意如何在此XML指定完整的类型名称。规则总是与一个类型。该规则的名字也相同,但因为它们是不同类型,它的确定。
RuleExec使编码工作轻松了许多。我们不必担心运行分析器自己或做了工作,是在上一节做任何的设置。下面的代码将创建一个命令,添加一个OrderItem,并更改该项目​​的单位数:
Order o = new Order();

OrderItem oi = o.NewItem(2.3f, 2);

o.Items.Add(oi);

RuleExec.ApplyRules(o);



oi.Units = 5;



Console.WriteLine("Before:");

Console.WriteLine("  Total: " + o.Total);



RuleExec.ApplyRules(oi);



Console.WriteLine("After:");

Console.WriteLine("  Total: " + o.Total);

看起来容易得多,是吧?下面是这段代码的输出结果:
Before:

  Total: 4.6

After:

  Total: 11.5
优先级和制止
虽然我猜字游戏,我发现它不能保证将运行规程规定英寸他们甚至不运行在相同的顺序,他们进入到规则集。有时,它是必要的运行在一个特定的顺序的规则。解决的办法是使用优先。
<DmRule cond="this.Foo == 5" name="Rule1" priority="2">

   <ThenStmts>

      <DmCdStmt xsi:type="Assignment" left="this.Bar" right="&quot;High&quot;" />

   </ThenStmt>

</DmRule>

<DmRule cond="this.Bar == &quot;High&quot;" name="Rule2" priority="1">

   <ThenStmts>

      <DmCdStmt xsi:type="Assignment" left="this.SomeProperty" right="true" />

   </ThenStmt>

</DmRule>

在此规则集的优先级属性显示的Rule1应该之前运行规则2。虽然它可能似乎的Rule1将在规则2运行反正,这是无法保证的。为了保证顺序,我们指定的优先级。在这种特殊情况下,正向链会接管,并认识到,我们改变了酒吧财产。如果规则1规则2运行前,可能发生的最坏的是,规则集运行两次。但是,想象一下你有几个规则,所有更改属性。除非你使用的优先次序,规则最终可能会运行比他们有更多的时间。
所需要的另一个特点是停止。 Workflow Foundation规则允许的暂停命令。这些命令可以插入到一个组,然后或其他行动的任何地方。对此我感到困惑的是,然后或其他行动允许的条件和循环,所以总有一个顺序流。因此,停止后的任何遥不可及。考虑到这一点,它是安全做出停止在一个规则的属性。
<DmRule cond="this.Foo &lt; 10" name="Rule1" haltAfterThen="true" 

        haltAfterElse="true" priority="1000">

   <ThenStmts>...</ThenStmts>

   <ElseStmts>...</ElseStmts>

</DmRule>

显然,停止默认为false,并且不需要指定。同样为优先。默认情况下,所有优先级均为零,和Workflow Foundation的决定,他们运行的顺序摘要
。。NET 3.0中新的Windows Workflow Foundation中添加了一个规则库,它可以是非常有用的。有次当你编写的应用程序,你觉得你需要规则,但没有工作流程。这是我已经把这个库的原因。微软提供了一个规则编写GUI,最终会写。规则文件,对与原始的源代码。这是对工作流的环境不错,但序列化是不是一个人类可读的格式。使用我的CodeDOM表达式解析器,我可以写在应用程序配置规则。我的目的是向人们介绍这个规则库,并给他们的能力嵌入到他们的应用程序规则。里面有什么
里面的文件列表:CodeDomExpParser - 我的CodeDOM表达式解析器库。DmCodeDom - CodeDom中的辅助库。Assignment.cs - 创建一个CodeAssignmentStatement。Declaration.cs - 创建一个CodeVariableDeclarationStatement。DmCdStmt.cs - 基类。 ExprStmt.cs - 创建一个CodeExpressionStatement。ForLoop.cs - 创建一个CodeIterationStatement。IfElse.cs - 创建一个CodeConditionStatement。DmCodeDom.TestHarness - NUnit的测试工具的DmCodeDom库。TestDmCd.cs - 包含在文章中提到的代码。DmRules配置\ DmRulesConfigHandler.cs - 配置节处理程序来读取应用程序配置的规则。DmRule.cs - 代表一个规则。DmRuleSet.cs - 保存所有的规则。DmRuleTypeSet.cs - 对同一个类型的规则。RuleExec.cs - 运行规则的静态辅助类。DmRules.TestHarness - DmRules NUnit的测试工具。BaseObject.cs - 一个基类,IsDirty属性。Order.cs - 订单类上面使用。OrderItem.cs - 上面使用的OrderItem类。TestDmRules.cs - 包含在文章中使用的代码。历史0.1:2006-06-20:初始版本
更新CodeDomExpParser库工作。NET 2.0中。创建与运行规则,每个类型的能力DmRules的初始版本。库的未来首要考虑的是跨类型链。0.2:2006-07-10:优先事项和制止
规则不能保证在任何特定的顺序运行。分配优先级,可以解决这个问题。有时,有必要停止处理其他规则,停止命令已添加这一点。

回答

评论会员:dukekujo 时间:2011/12/06
这是正常工作的整数值,而不是字符串值

新的任务("this.Price","100") - 工作
能否请你让我知道,如何分配一个字符串值的变量/属性。

新的任务("this.lookuptable","FaceAmount") - 不工作
评论会员:达斯汀Metzgar 时间:2011/12/06
这是与下面的字符串的语法罚款。感谢

新的任务("this.LookUpTable","\"FaceAmount \"")
评论会员:dukekujo 时间:2011/12/06
嗨达斯汀,
你的文章是当场上。这是接近我想要做什么。我想我会使用您的CodeDOM东西。虽然我仍然可以使用一些指针...

我的应用程序有一个报告的对象,它包含ReportItem对象(类似于您的订单和OrderItem的)。我想使用WF的规则集,以验证报告的对象,根据用户定义的规则。他们不会写规则的代码,但它会被写入他们根据他们的需求,并存储在数据库中。使用的几个例子,我的方式最有净... ...使用"ExternalRuleSet"例如,Bursteg"RuleExecutionWithoutWorkflow"。我卡上的一部分,我想,这样的规则进行评估时,移动到当时的分支,而不是设置一个对象的属性,我想补充报告规则的参考集合所谓ValidationResults。还应该加上一个参考的项目造成的错误(又名评价)。如果一个规则计算else分支,它应该尝试删除ValidationResults收集该规则的参考。由于规则的代码是有限的(即:没有声明),我想通报告的方法,我可以做这一切,并通过规则的名称,和"本"。最终目标,是用户可以提交报告,然后查看与之相关联的错误和警告的清单。所以... ... WF的规则集是动态用户驱动的验证,最好的方法?任何其他方式,或调整到这个?
评论会员:史蒂夫斯特朗 时间:2011/12/06
非常感谢。我收集你有一个报告和一个用户定义的规则(开发人员编码),经评估,将自己添加到报告ValidationResults集合。我假设,因为你不想分配在当时或else分支任何,这是不够的,只是知道哪些规则过去了,没有

我想什么利益我对你的做法是,你甚至懒得使用WF规则。 WF规则比你会找到像一个真正的规则引擎在BizTalk,ILOG等强大的少一点,但他们确实有正向链接和一些评估顺序的优化。但这些功能的问题,如果您Then或Else块做一些改变,他们正在评估的对象。由于您的报告对象不会改变规则的结果,你会不会利用这些功能的优势。如果我的理解是正确的(请告诉我,如果我错了),你只需要简单的计算结果为真或假的东西。

使用WF规则不会给你有一点点更复杂的规则,因为你可以使用的CodeDOM把它写的优势。使用ExternalRuleSet UI允许你写不写的CodeDOM规则。我做了这个项目,所以我可以在XML表达的规则,但可以很容易地创建自己的配置,因为你可以利用System.Workflow.Activities.Rules.Parser类的消息之一是显示在本文的。有些东西你可能要考虑的是企业库3.1的验证块,因为它可以包在一个像你想要什么样的结果的一切。先来看看{A4}]。他们甚至回升的类名ValidationResults。

验证应用程序块的校验器。如果需要的话,你可以建立自定义的。有没有验证程序,采取的CodeDOM(可能是因为他们能够在自定义属性表示)。但我很好奇,如果我的CodeDOM分析器可以适应作为一个自定义验证工作,验证块。不管怎么说,你有什么想法上使用验证块呢?

"噢...一个在不改变先生I'm我自己grandpardquo的历史教训; - 教授法恩斯沃斯
评论会员:驰援彼得罗夫 时间:2011/12/06
哎呀,验证应用程序块是新的我(尽管有相似的命名约定)。我从来没有在我的"动态验证"搜索偶然发现。它是什么,我试图完成的任务比WF规则更合适。因为我并不需要前瞻性链功能,WF规则集是没有必要的。我可能最终要纳入工作流程中的规则,但荷兰人在自己的博客中提到,应该很容易利用WF的VAB。现在我只需要搞清楚如何从数据库配置(或我的名字与用户名每个VAB的RuleSet,但web.config中会膨胀和可能非高性能),而不是拉的规则更加动态。感谢您指出我在正确的方向。
评论会员:达斯汀Metzgar 时间:2011/12/06
查找www.apprenticesystems.com
演示一些
评论会员:添麦柯迪 时间:2011/12/06
嗨,

也有另一种方式直接解析成RuleConditions和RuleActions字符串。有一个内部类System.Workflow.Activities.Rules.Parser的,可以通过该反射。举例包装:

公共类RuleParser
{
私人静态ConstructorInfo _ctor = NULL;
私有对象_parser = NULL;
私人常量的BindingFlags _flags的BindingFlags.Public | BindingFlags.NonPublic会| BindingFlags.Instance;

静态Rul​​eParser()
{

& #160; 类型为type = Assembly.GetAssembly(typeof运算(RuleValidation))的GetType("System.Workflow.Activities.Rules.Parser");
_ctor = type.GetConstructor(_flags的,空,新类型[] {typeof运算(RuleValidation)},NULL);

(_ctor == NULL)抛出新的回NotSupportedException();  60; }

公共RuleParser(RuleValidation验证)
{
  ; _parser = _ctor.Invoke(新对象[] {验证});
}

公共RuleExpressionCondition ParseCondition(字符串语句)
{
& #160; MethodInfo的MI = _parser.GetType()GetMethod("ParseCondition",_flags的);
返回(RuleExpressionCondition)mi.Invoke(_parser,新的对象[] {语句});
}

  ; 公共RuleAction ParseAction(字符串语句)
 60; {
MethodInfo的MI = _parser.GetType()GetMethod("ParseSingleStatement",_flags的);
返回(RuleAction)mi.Invoke(_parser,新的对象[] {语句});
 60; }

}

用法举例:

RuleValidation验证=新RuleValidation(typeof运算(订购),NULL);
RuleParser分析器=新RuleParser(验证);
RuleCondition条件= parser.ParseCondition("this.NumItems == 1)
RuleAction thenAction = parser.ParseAction("this.NumItems = 2");
RuleAction elseAction = parser.ParseAction("叫停");

溴,
驰援彼得罗夫
评论会员:达斯汀Metzgar 时间:2011/12/06
很酷。我的印象,该规则实用程序创建的CodeDOM语句的时候,其实,他们解析成一份声明中字符串。一些非常聪明的家伙,在微软工作。
评论会员:添麦柯迪 时间:2011/12/06
您好驰援,

我尝试这种技术,我用了一个WebService,但我总是异常:
"无法加载一个或多个请求的类型的更多信息,检索LoaderExceptions财产。"

但是当我试图在一个独立的窗体应用程序,它是没有问题的。
任何想法?
评论会员:WillemM 时间:2011/12/06
我已经被寻找不同的"规则"引擎,我就不能得到一件事直。为什么我会想对代码进行验证的规则呢?

作为一个业务应用的开发者,我宁愿有规则,验证作为一个整体的数据,这意味着一个DataTable的DataRow。据我所知,你可以用你的引擎,但它太多工作。不仅如此,你不能处理数据库中的存储过程相同的规则。

我宁愿有(和我目前的工作)是一种可以在数据库以及用户界面使用的RuleSet。因为我将可能永远要验证一个ComboBox时改变它的价值,但我会当用户去保存到数据库中的记录。大多数验证是正确的保存记录前或执行期间控制项的验证事件对用户界面的规则集。

无论如何,我只是不买成本规则引擎的MS或为此事的其他人。如果有人知道任何容易的发动机,lemme知道!
评论会员:游客 时间:2011/12/06
88Keys|添麦柯迪说:如果有人知道任何容易的发动机...我怕"易",你不会有多少运气。为了更容易,只要不使用规则。使用规则将添加另一层复杂性。当你写的最后期限下的业务应用程序,您必须使用什么尝试和真实的。你描述听起来像你要删除中间层,只是将规则应用于用户界面和数据。这听起来像一个有趣的项目。然而,即将到来的ADO.Net实体框架支持更加面向对象的立场和倾斜使用直数据集。配对规则和WindowsWorkflow就是一个很好的结合,海事组织。我怀疑微软将能卖企业的发展和稳健性的缓解。你我都知道,总是会有困难和某些事情,你不能这样做,所有这些新技术。但我怀疑在几年的时间,越来越多的企业应用将开发这种方式。我只是指。NET3.0一般,不是我的图书馆在这里。我只是想,这将是有趣写在XML的规则,并分析微软的代码是如何工作的。目前,我把一篇文章,使用该库的游戏规则应用于。有了它,我可以编辑配置文件的游戏作品:得分,推进到一个新的水平,游戏规则等的变化,如果你有兴趣,我可以让你知道什么时候公布的,所以你可以看到我是如何使用规则。{A5}
达斯汀Metzgar
评论会员:游客 时间:2011/12/06
右,有趣的是有状态,大多数文章的全部或大部分业务逻辑存储特效,以免有大量的代码重复统计研究所。然而,为什么都规则的基础上的用户界面或代码引擎?真的一切都归结规则是如何存储。现在,我看到了规则引擎写的CodeDOM或序列化为XML。如果他们在存储在DB的直观结构,那么它应该很容易解析和运行规则的数据库上下文。我已经开始制定这样一个规则引擎,但与一个额外的组件,可以下降到一个WinForm或WebForm中获得以及分配给它的规则。好了,反正我希望这最终会变得更加容易。
88Keys
评论会员:游客 时间:2011/12/06
添麦柯迪写道:是的,有趣的是,大多数的文章有状态的全部或大部分业务逻辑应该在存储的特效,以免有重复统计研究所大量的代码。然而,为什么都规则的基础上的用户界面或代码引擎?很简单:如果用户输入的应用程序错误的东西,他或她应该尽快对错误的通知。数据不应该被行驶到SQLServer的所有方法和存储过程,然后被唾弃,因为数据是错误的。真的没有完美的解决方案这个问题:将规则添加到UI中是最快的方法,让用户知道的东西与他所输入的数据是错误。作为一个数据库管理员,我想我的数据库中的规则,因为前端的开发人员可以有错,并尝试进入数据库的怪异的东西。这会导致开销,其逻辑上的人这样做,只是因为他们要保护自己的功能层。这种工作方式带来了另一个问题:数据库规则不同的是从业务逻辑规则,一个数据库可以为实体完整性和参照完整性检查,但仅此而已,如果你想使事情变得简单。业务逻辑可以参照和数据完整性检查与条件等,所以在技术上,存储在一个共同的数据存储的规则,是不是解决问​​题的办法,有很多imgsrc=http://www.orcode.com/upimg/2011_12_06_17_03_38_1.gifWM武器的大规模建设
?达斯汀Metzgar
评论会员:游客 时间:2011/12/06
我同意与蒂姆。规则引擎应集中于问题域,没有UI代码,甚至数据库的代码。规则定义本身应尽可能从UI或数据存储架构中删除。SQLServer2005中使用CLR的支持,它应该可以执行对一个共同的业务对象模型的规则,在DB中,用户界面​​,或两者兼而有之。
达斯汀Metzgar
评论会员:游客 时间:2011/12/06
88Keys写道:规则引擎应根据问题域为中心,而不是UI代码,甚至数据库的代码。规则定义本身应尽可能从UI或数据存储架构中删除。SQLServer2005中使用CLR支持,它应该有可能执行对一个共同的业务对象模型的规则,在DB中,用户界面​​,或两者要么我不明白你的发言。你说规则应该是从用户界面和数据库分开,但你想直接在数据库中的规则。n层的方法发生了什么事?也许这只是我,但退一步两级系统是一种回归,无论你的数据库规则引擎是如何看中。规则和工作流程,在手,要一个相当不错的中间层,不依赖于数据库。我应该能够在各种不同类型的数据源插件,而无需改变我的工作流程或我的业务规则。{A6}