Rule Evaluation and Object Inheritance
The Code Effects business rules engine supports evaluating descendant source objects. To illustrate this concept, create one base class and two classes that inherit from it:
using System;
public class MyBase
{
public int ID { get; set; } = 0;
public string Name { get; set; }
}
public class MySourceOne : MyBase
{
public DateTime Date { get; set; } = DateTime.MinValue;
}
public class MySourceTwo : MyBase
{
public TimeSpan Time { get; set; } = TimeSpan.MinValue;
}
Assume we also have an evaluation type rule that uses only the base class' fields, like this:
Check if ID is greater than 0 and Name starts with A
If we define instances of all three classes, the Evaluator can evaluate each instance against this rule because it relies solely on members declared in the base class, and those members are available to all of its descendants:
using CodeEffects.Rule.Engine;
var zero = new MyBase { ID = 0, Name = "abc" };
var one = new MySourceOne { ID = 1, Name = "xyz" };
var two = new MySourceTwo { ID = 2, Name = "abc" };
// Retrieve Rule XML from your storage
string ruleXml = GetRuleXmlFromSomewhere();
var evaluator = new Evaluator<MyBase>(ruleXml);
bool success = evaluator.Evaluate(zero); // Returns False
success = evaluator.Evaluate(one); // Returns False
success = evaluator.Evaluate(two); // Returns True
Notice that we created an instance of the Evaluator using the base type, yet we were able to pass instances of all three classes for evaluation without any exceptions. The non-generic Evaluator works the same way. Give it the base type and EvaluationParameters, which can be a default instance:
var evaluator = new Evaluator(typeof(MyBase), ruleXml, new EvaluationParameters());
Which Rules an Evaluator Accepts
Every rule in Rule XML records the type of the source object it was written for. The Evaluator loads only the rules whose type is the type you gave to the Evaluator, or one of its ancestors:
- A rule written for the base class can be evaluated by an
Evaluator of the base class and by an Evaluator of any of its descendants. This is what the example above shows.
- A rule written for a descendant uses members that its ancestors do not have, so an
Evaluator of the base class does not load it. If the Rule XML holds no rule that the Evaluator can load, its constructor throws an EvaluationException with the control number RF2747. Create the Evaluator with the descendant type instead, and pass it instances of that descendant:
var evaluator = new Evaluator<MySourceOne>(ruleXml);
In a ruleset, an Evaluator skips the rules that it cannot load and keeps the others.
The Rule Editor follows the same logic. Its source object is the one you give to it, so rule authors see the members of the base class only if the base class is the source object of the editor.