Building a rule engine in c# (part 4: extending the rule engine to evaluate defined expressions)

In the first three posts of building a rule engine in c# building a rule engine in c#, building a rule engine in c# (part 2: extending the rule engine to handle collections), building a rule engine in c# (part 3: extending the rule engine to handle aggregations of collections) the definition of the rules are very basic and did not look very clear. So i decided to implement an expression evaluator. With this expression evaluator the definition of the rules becomes much clearer. I will show the difference in the next three pictures. The first one shows the definition of the rules how i described it in the past three posts.

ProcessingEngineDatabase

This second picture shows the definition with a expression evaluator.

ComplexProcessingRule

If we use a expression evaluator we can also use logical combinators (and, or) to combine the defined rules. The third picture shows how the processing rules would look like if they are combined.

ComplexProcessingRuleCombinator2

The problem with that processing rules is that in the first three post i used expression trees to generate the rules but i had the seperate parts of the rules and so i needed no parser. Now we have to develop a parser that parses the expression and an evaluator that checks the overtaken object against the parsed expression. In this post i will show how to use the expression evaluator i posted at codeplex (https://simpleexpeval.codeplex.com/) to validate a given object against the defined rule. In the additional blog post implementing an expression evaluator in c# i describes how the expression evaluator works. But in this post i will describe how to use it to define the rules you need to check your object again. The expression evaluator support the following operators:

  • open bracket ‘(‘ and close bracket ‘)’
  • addition ‘+’
  • subtraction ‘-‘
  • multiblication ‘*’
  • division ‘/’
  • modulo ‘%’
  • equality ‘=’
  • unequality ‘!=’
  • bigger than ‘>’
  • bigger than or equal ‘>=’
  • smaller than ‘<‘
  • smaller than or equal ‘<=’
  • logical and ‘&&’
  • logical or ‘||’

and the following data types:

  • integer ’10’
  • double ‘10.2’
  • string ‘”test”‘
  • boolean ‘true’ or ‘false’

This is a example how to use the expression evaluator with a defined person that is evaluated against a rule. That is the definition of the person class:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public int Children { get; set; }
    public bool Married { get; set; }
}

Now the defined rule text (” (Children = 2 && Married = true) || Age > 36 “) is evaluated against the defined person object.

Person person = new Person() { Name = "Mathias", Age = 36, Children = 2, Married = true };
RuleLoader ruleLoader = new RuleLoader();
Rule processingRule = ruleLoader.LoadProcessingRule(5);
//processingRule.ProcessingRule = " (Children = 2 && Married = true) || Age > 36 ";
Evaluator evaluator = new Evaluator();
var evaluatorResult = evaluator.Evaluate<Person>(ruleText, person);

The evaluatorResult is true because the person object has two children and is married. Here is a second example that shows that it is possible to use properties at any possition in the rule text.

Person person = new Person() { Name = "Mathias", Age = 36, Children = 2, Married = true };
RuleLoader ruleLoader = new RuleLoader();
Rule processingRule = ruleLoader.LoadProcessingRule(5);
//processingRule.ProcessingRule = " Name != 'test' && Children <= Age / 20 "; 
Evaluator evaluator = new Evaluator(); 
var evaluatorResult = evaluator.Evaluate<Person>(ruleText, person);

The evaluatorResult is also true because Age / 20 is smaller than Children and the name is unequal ‘test’. If you want to use the expression evaluation engine you can download it from codeplex (https://simpleexpeval.codeplex.com/) and add a reference in your visual studio project. Then you can use the Evaluator class to evaluate the defined rule text against an overtaken object. In the blog post implementing an expression evaluator in c# i describe the implementation of the expression evaluator and in the post building a rule engine in c# (part 5: bringing it all together) i try to give an overview of the usage of the ruleengine.codeplex.com project.

Advertisements

39 Comments on “Building a rule engine in c# (part 4: extending the rule engine to evaluate defined expressions)”

  1. Martin says:

    1. Kindly advice how can I modify the engine so that it can handle DateTime. eg. Person.Birthday 20, It should return the count of Persons whose Age > 20.

    I am a beginner in C#, so any code would be greatly appreciated

    regards
    Martin

    • netmatze says:

      Hello Martin,

      To accomplish the task you want, you have to extend the class RuleValidator in the rule engine project. You need a new method that checks your overtaken values against one ore more rules.
      The simpler version is the first one:

      public int ValidateRuleCount(T[] values, Func rule)
      {
      var count = 0;
      foreach (var value in values)
      {
      if (rule(value))
      count++;
      }
      return count;
      }

      I have added it to the source code of the rule engine (ruleengine.codeplex.com). If you need to validate against more than one rule you need the following method:

      public int ValidateRulesCount(T[] values, Func[] rules)
      {
      var count = 0;
      foreach (var value in values)
      {
      var passedAllRules = true;
      foreach (var rule in rules)
      {
      if (!rule(value))
      passedAllRules = false;
      }
      if (passedAllRules)
      count++;

      }
      return count;
      }

      Here is the test i wrote to check if it works.

      public void SimpleRuleLoaderPersonValidateRulesCount()
      {
      Person person1 = new Person()
      {
      Name = “Mathias”,
      Birthdate = new DateTime(1976, 5, 9)
      };
      Person person2 = new Person()
      {
      Name = “Anna”,
      Birthdate = new DateTime(2001, 4, 4)
      };
      Rule rule1 = new Rule(“Birthdate”, Operator.GreaterThanOrEqual, new DateTime(2000, 1, 1));
      RuleEngine.RuleEngine ruleEngine = new RuleEngine.RuleEngine();
      var ruleFunc =
      ruleEngine.CompileRule(rule1);
      RuleValidator ruleValidator = new RuleValidator();
      // calculates the count of persons that match rule1
      var resultSingleRule = ruleValidator.ValidateRuleCount(new[] { person1, person2 }, ruleFunc);
      // one person (“Anna”) matches the Birthdate rule
      Assert.AreEqual(resultSingleRule, 1);
      Rule rule2 = new Rule(“Name”, Operator.Equal, “Anna”);
      var combinedRulesFunc =
      ruleEngine.CombineRules(new Rule[] { rule1, rule2 });
      // calculates the count of persons that match rule1 and rule2
      var resultMultibleRule = ruleValidator.ValidateRulesCount(new[] { person1, person2 }, combinedRulesFunc);
      // one person (“Anna”) matches the Birthdate rule and the Name rule
      Assert.AreEqual(resultMultibleRule, 1);
      }

      I hope that code helps you to accomplish your goal.

      • Martin says:

        Thanks!!
        Also, how would I do the same thing using the expression evaluator ?

        When I tried something like ruleValidator.ValidateExpressionRules(PersonList, new Rule(“Birthdate< '2001-09-05'")); It threw an exception

        Kindly advice.
        -Martin

      • netmatze says:

        Hello Martin,

        The problem was, that my SimpleExpressionEvaluator could only work with String, Boolean, Double and Integer values. I now added the support for DateTime. You only need to get the newest version from ruleengine.codeplex.com. I wrote the following test and checked it in to show how it works.

        [TestMethod]
        public void SimpleExpressionEvaluatorRules()
        {
        Person person1 = new Person()
        {
        Name = “Mathias”,
        Age = 36,
        Children = 2,
        Married = true,
        Birthdate = new DateTime(1976,5,9)
        };
        Person person2 = new Person()
        {
        Name = “Anna”,
        Age = 32,
        Children = 2,
        Married = false,
        Birthdate = new DateTime(2002,2,2)
        };
        RuleEngine.RuleEngine ruleEngine = new RuleEngine.RuleEngine();
        RuleValidator ruleValidator = new RuleValidator();
        var counter = ruleValidator.ValidateExpressionRulesCount(
        new Person[] { person1, person2 }, new Rule[] { new Rule(“Birthdate < '2001-09-05'") });
        // only one Person ("Anna") has a birthdate that is smaller then '2001-09-05'
        Assert.AreEqual(counter, 1);
        }

        I hope that helps.

        Greetings
        netmatze

  2. Martin says:

    Hello,
    Appreciate all your help and especially the code samples.
    Martin

  3. Martin says:

    Hello Netmatze,
    I get an exception when I pass a List instead of Rule[] in “SimpleRuleLoaderPersonEvaluateExpressionAny” : Kindly advice how to fix it,

    Martin
    ==========
    [TestMethod]
    public void SimpleRuleLoaderPersonEvaluateExpressionAny()
    {
    Person person1 = new Person() { Name = “Mathias”, Age = 36, Children = 2 };
    Person person2 = new Person() { Name = “Anna”, Age = 35, Children = 2 };
    ExpressionRuleLoader expressionRuleLoader = new ExpressionRuleLoader();
    // new Rule(” Name = ‘mathias’ “);
    Rule rule1 = expressionRuleLoader.Load(1);
    // new Rule(” Age = 35 “);
    Rule rule2 = expressionRuleLoader.Load(2);

    //////// Here I create a Rules list ///////
    List Rules = new List();
    Rules.Add(new Rule(” Name = ‘mathias’ “));
    Rules.Add(new Rule(” Age = 35 “));

    RuleValidator ruleValidator = new RuleValidator();
    var result = ruleValidator.ValidateExpressionRulesAny(new Person[] { person1, person2 },
    new Rule[] { rule1, rule2 }); // <—– This works
    //Rules); //<—- This does not, and throws an exception
    ===========

    • Martin says:

      Hello netmatze,
      In the previous post I forgot to mention that I had overloaded the method to take an IEnumerale rules.

      One more question. I would like to create an Operator.FoundIn. I would then like to use it like:
      List NameList = Repository.GetNames(); // This returns say 10,000 names
      Rule rule1 = new Rule(“Name”, Operator.FoundIn, NameList);

      Kindly advice.
      Martin

      • Martin says:

        Sorry, it should be List NameList = Repository.GetNames()
        -Martin

      • netmatze says:

        Hello Martin,

        The operation you need is a little bit trickey to implement, because all other operations (Equal, Unequal, LessThan …) are buildin funktions in Expression Trees. What you need requires a much more complicated Expression Tree. You can see the implementation it the ExpressionBuilder class. Here is the test that shows how to use the Operator.FoundIn operator:
        [TestMethod]
        public void SimpleRuleLoaderPersonEvaluateFoundInExpression()
        {
        Person person1 = new Person() { Name = “Mathias”, Age = 36, Children = 2 };
        Person person2 = new Person() { Name = “Anna”, Age = 35, Children = 2 };
        Person person3 = new Person() { Name = “Emil”, Age = 4, Children = 0 };

        List persons = new List();
        persons.Add(person1);
        persons.Add(person2);

        RuleEngine.RuleEngine ruleEngine = new RuleEngine.RuleEngine();
        var ruleFunc =
        ruleEngine.CompileRule(“Name”, Operator.FoundIn, persons);
        var result = ruleFunc(person1);

        Rule rule = new Rule(“Name”, Operator.FoundIn, persons);
        var ruleFuncRule =
        ruleEngine.CompileRule(rule);

        var ruleFuncRuleResult = ruleFuncRule(person3);
        Assert.AreEqual(result, true);
        Assert.AreEqual(ruleFuncRuleResult, false);
        }
        I hope that helps.
        netmatze

    • netmatze says:

      Hello Martin,

      I have now implemented the ValidateExpressionRulesAny method with T[] and a List.
      Here is the test i wrote:
      [TestMethod]
      public void SimpleRuleLoaderPersonEvaluateExpressionAny()
      {
      Person person1 = new Person() { Name = “Mathias”, Age = 36, Children = 2 };
      Person person2 = new Person() { Name = “Anna”, Age = 35, Children = 2 };

      List rules = new List();
      rules.Add(new Rule(” Name = ‘Mathias’ “));
      rules.Add(new Rule(” Age = 35 “));

      RuleValidator ruleValidator = new RuleValidator();
      var result = ruleValidator.ValidateExpressionRulesAny(new Person[] { person1, person2 },
      rules);
      Assert.AreEqual(result, true);
      }
      I have checked it in.

  4. Mike says:

    Hi netmatze,

    Thanks for sharing this code – It’s really great and obviously much effort was put in originally – It’s much appreciated and I’ve learnt a lot from it,

    Could you give me some ideas on how to create a “Then” part of an expression? e.g.
    If Age > 20 and Children=2 Then SetCanReceiveBenefits(True)

    where SetCanReceiveBenefits is a method on the original object that’s passed in?

    Much appreciated

    Mike

    • netmatze says:

      Hello Mike,

      I implemented it with a methodcall too. I added a SetCanRecieveBenefits(bool receiveBenefits) method to the person class.
      public class Person
      {
      public string Name { get; set; }
      public int Age { get; set; }
      public int Children { get; set; }
      public bool Married { get; set; }
      public DateTime Birthdate { get; set; }
      public Adresse Adresse_ { get; set; }
      public bool ReceiveBenefits { get; set; }
      public void SetCanReceiveBenefits(bool receiveBenefits)
      {
      ReceiveBenefits = receiveBenefits;
      }
      private List adresses = new List();
      public List Adresses_
      {
      get { return adresses; }
      set { adresses = value; }
      }
      }
      Here is the test i checked it in in the ruleengine project.
      [TestMethod]
      public void SimpleExpressionEvaluatorWithSetMethod()
      {
      Person person1 = new Person()
      {
      Name = “Mathias”,
      Age = 36,
      Children = 2,
      Married = true,
      Birthdate = new DateTime(1976, 5, 9)
      };
      Person person2 = new Person()
      {
      Name = “Anna”,
      Age = 32,
      Children = 2,
      Married = false,
      Birthdate = new DateTime(2002, 2, 2)
      };
      Evaluator evaluator = new Evaluator();
      var result = evaluator.Evaluate(” (Age > 10) set SetCanReceiveBenefits(true) “, person1);
      Assert.AreEqual(result, true);
      Assert.AreEqual(person1.ReceiveBenefits, true);
      }

      Greetings
      netmatze

  5. Martin says:

    Hello Netmatze,
    It looks like when an object has a property say “1224-5” that needs evaluation, in the ExpressionEvaluatorExecutor.Evaluate(List postfixList,Dictionary symbolTable, T objectValue) method, it parses it as a datetime and assigns a DateTimeNode instead of a StringNode.
    Kindly advice how I can fix it.

    Regards
    Martin

    • netmatze says:

      Hello Martin,

      You are right there was a bug in the ExpressionEvaluatorExecutor class. I fixed it and checked it in.

      greetings
      netmatze

      • Martin says:

        Hi Netmatze,
        It still seems to have a bug.
        If I set Person person1 = new Person() { Name = “8302-2″, Age = 35, Children = 2 }; and then have the Rule in the ruleexpressionloader to->case 1: return new Rule(” Name = ‘8302-2’ “), then var result = ruleValidator.ValidateExpressionRules(person1, rule1) returns false eventhough the Name property is the same as in the Rule.

        regards
        Martin

      • Martin says:

        Hi Netmatze,
        I added a fix in evaluate in Expressionevaluator.c where it incorrectly parsed a string like “8202-2” as a DateTime. Below is what I did:
        1. string[] formats = {“M/d/yyyy h:mm:ss tt”, “M/d/yyyy h:mm tt”,
        “MM/dd/yyyy hh:mm:ss”, “M/d/yyyy h:mm:ss”,
        “M/d/yyyy hh:mm tt”, “M/d/yyyy hh tt”,
        “M/d/yyyy h:mm”, “M/d/yyyy h:mm”,
        “MM/dd/yyyy hh:mm”, “M/dd/yyyy hh:mm”};
        2.else if (DateTime.TryParseExact(value.ToString(),
        formats,
        new CultureInfo(“en-US”),
        DateTimeStyles.None,
        out dateTimeOutValue))
        {
        DateTimeNode dateTimeNode = new DateTimeNode();
        dateTimeNode.Value = dateTimeOutValue;
        valueStack.Push(dateTimeNode);
        }
        // Commented out the old
        //else if (DateTime.TryParse(value.ToString(), out dateTimeOutValue))
        //{
        // DateTimeNode dateTimeNode = new DateTimeNode();
        // dateTimeNode.Value = dateTimeOutValue;
        // valueStack.Push(dateTimeNode);
        //}

        Kindly advice if it makes sense and if this correction is needed anywhere else or If I need to make any more corrections.

        Regards
        Martin

      • netmatze says:

        Hello Martin,

        If that works for you scenario that is super and much better then the old solution.
        The problem is it only works for us date format.
        I will think about it the next days and try to find a general solution.

        greetings
        netmatze

  6. fizz says:

    Hello netmaze. i am a c# beginner i really dont know how to implement a rule engine in c#. i wanted to suggest dress to the blind person according to their color complexion. Suppose
    if a person having fair complexion, and height greater than 5 feet ,and event is wedding then engine must display a list of dresses of medium size for wedding from the table. can you please help me how t implement this idea?

    • netmatze says:

      Hello Fizz,

      With the rule engine you could do the following:

      Lets say you have a EventPerson:
      public class EventPerson
      {
      public string Name { get; set; }
      public int ColorComplexion { get; set; }
      public int Height { get; set; }
      public string Event { get; set; }
      public int DressNumber { get; private set; }

      public void SetDressNumber(int dressNumber)
      {
      DressNumber = dressNumber;
      }
      }

      Now you want to use the rule engine to check properties of the EventPerson to set the DressNumber of the Person. You could do that the following way:
      EventPerson person1 = new EventPerson()
      {
      Name = “Mathias”,
      ColorComplexion = 5,
      Height = 10,
      Event = “Wedding”
      };
      Evaluator evaluator = new Evaluator();
      bool result = evaluator.Evaluate(
      ” (ColorComplexion > 4 && Height > 5 && Event = ‘Wedding’) then SetDressNumber(5) “, person1);
      Assert.AreEqual(person1.DressNumber, 5);

      So in that case the rule engine would set the DressNumber of the person1 to 5. But i have to say that i am not sure if that is what you need. Is it important for you to save the combined rule in a string? Or do you just need to check the Properties of a specific Person object and return a list of specific Dress objects?

      Greetings
      netmatze

  7. fizz says:

    Thanks netmatze for replying. i want to check the properties for all the users and return a list of dresses according to the event cz blind have no idea about fashion and color combination. i want to display them dresses. i extract their skin tone from the captured image.

  8. fizz says:

    i also want to add inference ability ? tell me how i can add here? suppose if a user just want to buy with in a specified range of price ,but his desiring stuff or color is out of range then my system should display in other similar color shade dresses within lower price range. how i can add such thing in rule engine ?

    • netmatze says:

      Hello fizz,

      I am sorry but i do not understand for what you need the rule engine. Why dont you just check the properties of the blind person and then return a list of dresses?

      Greetings
      netmatze

  9. fizz says:

    Hello Netmatze
    i need rule engine for the selection of dresses , shoes and other personal accessories especially for blind and visual impaired person. Now suggest me what should i need to do in rule engine implementation? if you will guide me for one accessory like dresses then it will be easy for me to extend it for other accessories.

    • netmatze says:

      Hello Fizz,

      If you want my help for your implementation you need to post some code. How does your dresses class look like (what properties fields methods). How does your blind person class look, how are the dresses and shoes connected with the blind persons and what are the properties of the blind persons that are used to find the right dresses and shoes? Then i can maybe tell you if and how you should use the rule engine.

  10. Peter says:

    Hi Netmatze,
    I am trying to use the SimpleExpresionEvaluator dll using Reflection.
    Here is what I have so far.

    Person person2 = new Person()
    {
    Name = “Anna”,
    Age = 32,
    Children = 2,
    Married = false
    };
    Dictionary result = new Dictionary {
    {“p1”,3},
    {“p2″,”ee”},
    {“p3”,2}
    };

    Dictionary dicPro = new Dictionary();
    Dictionary dicValue = new Dictionary();
    foreach (var o in result)
    {
    dicPro.Add(o.Key, o.Value.GetType());
    dicValue.Add(o.Key, o.Value.ToString());
    }

    //This is going to return a run time created object of Type MyType, this object has as many properties as passed in the Dictionary result with those values.

    var DashboardObject = TypeCreator.CreateObject(dicPro, dicValue);

    Evaluator evaluator = new Evaluator();
    // this should return true but is returning false
    var method = evaluator.GetType().GetMethod(“Evaluate”).MakeGenericMethod(DashboardObject.GetType());
    var evaluatorResult1 = method.Invoke(evaluator, new object[] { “p1 = 3”, DashboardObject });
    // I used this as test and it is returning true
    var evaluatorResult = evaluator.Evaluate(“Age = 32”, person2);

    Could you help me to figure out why is this happening, I can provide you with the source to create the run time object if you need it for testing.
    Thanks in advance.

    • netmatze says:

      Hello Peter,

      I read your code and my first question is does your DashboardObject have a property p1?
      If the answer is true then you have to send me the code that generates the DashboardObject too, because then i have to generate such an object and debug the Expression Evaluator to give you a significant answer.

      Greetings
      netmatze

      • Peter says:

        Hello netmatze,
        Thanks for your fast response.
        Here I’m sending you the code to generate a class dynamically.
        I am not sure if the code will be truncated but I can’t find any way to send you the file itself.

        Thanks again.

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Reflection.Emit;
        using System.Reflection;
        using System.Threading;
        using System.ComponentModel;

        namespace RuleDLL
        {
        public class MetricDashboardType
        {
        public int Key { get; set; }
        }

        public class TypeCreator
        {
        public static object CreateObject(Dictionary propDict, Dictionary valueDict)
        {
        Type dynamicType = CreateNewType(“MetricTypeName”, propDict, typeof(MetricDashboardType));
        MetricDashboardType newClassBase = (MetricDashboardType)Activator.CreateInstance(dynamicType);
        dynamic newClass = newClassBase;
        foreach (var o in valueDict)
        {
        Type propType = propDict[o.Key];
        var property = TypeDescriptor.GetProperties(newClass)[o.Key];
        var convertedValue = property.Converter.ConvertFrom(o.Value);
        property.SetValue(newClass, convertedValue);
        }
        return newClass;
        }
        public static Type CreateNewType(string newTypeName, Dictionary dict, Type baseClassType)
        {
        bool noNewProperties = true;
        // create a dynamic assembly and module
        AssemblyBuilder assemblyBldr = Thread.GetDomain().DefineDynamicAssembly (new AssemblyName(“tmpAssembly”), AssemblyBuilderAccess.Run);
        ModuleBuilder moduleBldr = assemblyBldr.DefineDynamicModule(“tmpModule”);

        // create a new type builder
        TypeBuilder typeBldr = moduleBldr.DefineType(newTypeName, TypeAttributes.Public | TypeAttributes.Class, baseClassType);

        // Loop over the attributes that will be used as the
        // properties names in my new type
        string propertyName = null;
        Type propertyType = null;
        var baseClassObj = Activator.CreateInstance(baseClassType);
        foreach (var word in dict)
        {
        propertyName = word.Key;
        propertyType = word.Value;

        //is it already in the base class?
        var src_pi = baseClassObj.GetType().GetProperty(propertyName);
        if (src_pi != null)
        {
        continue;
        }

        // Generate a private field for the property
        FieldBuilder fldBldr = typeBldr.DefineField (“_” + propertyName, propertyType, FieldAttributes.Private);
        // Generate a public property
        PropertyBuilder prptyBldr = typeBldr.DefineProperty(propertyName, PropertyAttributes.None, propertyType, new Type[] { propertyType });
        // The property set and property get methods need the
        // following attributes:
        MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;
        // Define the “get” accessor method for newly created private field.
        MethodBuilder currGetPropMthdBldr = typeBldr.DefineMethod (“get_value”, GetSetAttr, propertyType, null);

        // Intermediate Language stuff… as per Microsoft
        ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
        currGetIL.Emit(OpCodes.Ldarg_0);
        currGetIL.Emit(OpCodes.Ldfld, fldBldr);
        currGetIL.Emit(OpCodes.Ret);

        // Define the “set” accessor method for the newly created private field.
        MethodBuilder currSetPropMthdBldr = typeBldr.DefineMethod(“set_value”, GetSetAttr, null, new Type[] { propertyType });

        // More Intermediate Language stuff…
        ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
        currSetIL.Emit(OpCodes.Ldarg_0);
        currSetIL.Emit(OpCodes.Ldarg_1);
        currSetIL.Emit(OpCodes.Stfld, fldBldr);
        currSetIL.Emit(OpCodes.Ret);

        // Assign the two methods created above to the
        // PropertyBuilder’s Set and Get
        prptyBldr.SetGetMethod(currGetPropMthdBldr);
        prptyBldr.SetSetMethod(currSetPropMthdBldr);
        noNewProperties = false; //I added at least one property
        }

        if (noNewProperties == true)
        {
        return baseClassType; //deliver the base class
        }
        // Generate (and deliver) my type
        return typeBldr.CreateType();
        }
        }
        }

      • netmatze says:

        Hello Peter,

        Thanks for your code i tried it and found the problem. It has nothing to do with your dynamic object. The problem is that you used ‘p1’ as the name for the property. My expression evaluator uses a lexer to convert the string ‘p1 = 3’. The problem is it worked only with letters in the property name and not with numbers. I fixed that problem so now it works with the new version i released at codeplex. You could also change the name of the property from ‘p1’ to ‘pOne’ that would also work.

        Greetings
        Netmatze

  11. Peter says:

    Hi netmatze,
    This works like a charm.
    You have create a really solid solution.
    Thanks

  12. Damien Steiger says:

    Hi netmaze,

    Thanks for the great utility.

    I am trying to use it to perform some partial string comparisons like StartsWith, EndsWith, Contains.

    I looked at your tests and see this type of test:

    var result2 = evaluator.Evaluate(
    ” Name like ‘ann?’ “, person2);

    This doesn’t want to work for me. I have a property called Name, the value of which is ‘belt’. I get a false result when using a similar test such as:

    var result2 = evaluator.Evaluate(
    ” Name like ‘bel?’ “, myObject);

    My code is using the ValidateExpressionRulesAll() method with an array of objects and an array of rules. I tried the above example in an attempt to simplify things and see if I could detect why I don’t get a true result as I expect.

    Any help would be greatly appreciated.

    Thanks,
    Damien

    • netmatze says:

      Hello Damien,

      I have implemented the like operator but only for ‘?’ and ‘%’ at the end of the expression. That means the following two things would work “Name like ‘ann?'” and “Name like ‘ann%'”.
      If you could post me your myObject and the code how you use it i could help you.

      Greetings netmatze

      • Damien Steiger says:

        Hi netmaze,

        Thanks very much for the quick reply. Turns out I didn’t have the LikeParser.dll file in my bin directory. I wasn’t getting any exceptions.. just a false result when executing validation. Once I discovered this and put the dll in place it started working as expected.

        Thanks again,
        Damien

  13. Shaik Dawood. says:

    Hi,
    This is very very helpful for my project. I am trying to implement the “Operator.FoundIn” functionality that Martin discussed on 22/10/2013. I am struggling with it. Can Martin or NetMaze help me in providing the code for it.

    Thanks,
    Shaik Dawood.

    • netmatze says:

      Hello Shaik,

      The Operator.FoundIn is allready implemented. If you download the RuleEngine source code there is a test case SimpleRuleLoaderPersonEvaluateFoundInExpression. It looks the following:

      Person person1 = new Person() { Name = “Mathias”, Age = 36, Children = 2 };
      Person person2 = new Person() { Name = “Anna”, Age = 35, Children = 2 };
      Person person3 = new Person() { Name = “Emil”, Age = 4, Children = 0 };

      List persons = new List();
      persons.Add(person1);
      persons.Add(person2);
      persons.Add(person3);

      RuleEngine.RuleEngine ruleEngine = new RuleEngine.RuleEngine();
      var ruleFunc =
      ruleEngine.CompileRule(“Name”, Operator.FoundIn, persons);

      var result = ruleFunc(person1);

      Rule rule = new Rule(“Name”, Operator.NotFoundIn, persons);
      var ruleFuncRule = ruleEngine.CompileRule(rule);

      var ruleFuncRuleResult = ruleFuncRule(person3);
      Assert.AreEqual(result, true);
      Assert.AreEqual(ruleFuncRuleResult, false);

      Greetings netmatze

  14. Tushar Verma says:

    Hi There,

    Thanks for this great piece of code. Could you please advice that how would this rule engine handle a situation with negative numbers? For e.g. A <= -100, where A = -200 gives false, even if its true

  15. Green Thomas says:

    can you implement regex inside the rules editor window?

  16. bcriner says:

    I have a question. How can I evaluate the property of an object to another property? For example, in my app, I am dealing with insurance claims. The claim is my object. It has two properties, LossDate and PolicyEffectiveDate. How can I have a rule like “Object.LossDate >= Object.PoicyEffectiveDate”


If you have a note or a question please write a comment.

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s