Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

Custom Rule Engine in WPF - MVVM

, 11 Sep 2010
Custom Rule Engine approach which can evaluate complex combinations of business rules. A sample application is provided in WPF following the MVVM pattern.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace CustomRulesMVVM.Models
{
    class RuleHelper
    {
        #region Members
        private const string EQUAL = "=";
        private const string NOT_EQUAL = "!=";
        private const string GREATER_THAN = ">";       
        private const string LESSER_THAN = "<";
        #endregion

        #region Private Methods
        /// <summary>
        /// Get value of a property from an object using Reflection
        /// </summary>
        /// <param name="objSource"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private static object GetValueFromObject(object objSource, object propertyName)
        {
            if (null != objSource)
            {
                PropertyInfo[] properties = objSource.GetType().GetProperties();
                foreach (PropertyInfo info in properties)
                {
                    if (info.Name.ToUpper() == propertyName.ToString().ToUpper())
                    {
                        return info.GetValue(objSource, null);
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// This method compares two valus with based on given operating code. Value can be any type and type is checked inside
        /// eg. send ("True","True","=") for comapring two booleans
        /// ("25","20",">") for comparing two integers
        /// </summary>
        /// <param name="valueLHS"></param>
        /// <param name="valueRHS"></param>
        /// <param name="operatorCode"></param>
        /// <returns></returns>
        private static bool ComapareValues(string valueLHS,string valueRHS,string operatorCode)
        {
            bool isBool, isNumeric, isDateTime;
            bool boolValue1, boolValue2 = false;
            double numericValue1, numericValue2 = 0.0;
            DateTime dateValue1, dateValue2 = DateTime.Today;

            try
            {
                //Check if incoming values are boolean/Numeric/Date else it is string
                isBool = Boolean.TryParse(valueLHS, out boolValue1) && Boolean.TryParse(valueRHS, out  boolValue2);
                isNumeric = Double.TryParse(valueLHS, out numericValue1) && Double.TryParse(valueRHS, out numericValue2);
                isDateTime = DateTime.TryParse(valueLHS, out dateValue1) && DateTime.TryParse(valueRHS, out dateValue2);

                //Do comparisons based on value types
                if (operatorCode == EQUAL && (!isBool && !isNumeric && !isDateTime)) //Comparing equal condition of two string values
                    return valueLHS.Equals(valueRHS, StringComparison.InvariantCultureIgnoreCase);
                else if (operatorCode == EQUAL && isNumeric) //Comparing if two numbers are equal
                    return numericValue1 == numericValue2;
                else if (operatorCode == GREATER_THAN && isNumeric) //Checking if Number 1> Number 2
                    return numericValue1 > numericValue2;
                else if (operatorCode == LESSER_THAN && isNumeric) //Checking if Number 1 < Number 2
                    return numericValue1 < numericValue2;
                else if (operatorCode == EQUAL && isBool) //Checkingif two boolean values are equal
                    return boolValue1 == boolValue2;
                else if (operatorCode == EQUAL && isDateTime) //Checking if two datetime values are equal
                    return dateValue1.Equals(dateValue2);
                else
                    return false;
            }
            catch (Exception)
            {
                return false; 
            }            
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Comparing whether a property value of objSource with customRule.ValueRHS
        /// eg. objSource = Country object, customRule.CodeLHS is CountryName; First valueLHS
        /// (value given by user for CountryName in Country object) is evaluated
        /// using reflection. It is checked with valueRHS (here USA). Similarly for other objects
        /// and properties
        /// </summary>
        /// <param name="customRule"></param>
        /// <param name="objSource"></param>
        /// <returns></returns>
        public static bool EvaluatePropertyValue(CustomRule customRule,object objSource)
        {
            object valueLHS = GetValueFromObject(objSource, customRule.CodeLHS);
            return ComapareValues(Convert.ToString(valueLHS), customRule.ValueRHS, customRule.Operator);
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Renil Joy, Bangalore
Software Developer (Senior) Societe Generale
India India
I am a .Net developer, currently working with Societe Generale Global Solution Centre, Bangalore and was previously with Cognizant.I have more than 8 years of .Net experience in BFSI domain. I am an experienced developer in C#, VB.Net, Silverlight, WPF, WCF, LINQ, Entity Framework, SSIS, NHibernate, ASP.Net and SQL Server.
Follow on   LinkedIn

You may also be interested in...

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 12 Sep 2010
Article Copyright 2010 by Renil Joy, Bangalore
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid