Rules engine dynamic type casting I have a basic switch statement that executes some code on expectedValue and givenValue. The code to execute is guided by the variable actionToApply. This leaves one more variable that is fieldTypeName. This essentially guides the code in to casting the values to the type defined by fieldTypeName - if needed.

I was hoping to have the switch block reviewed/refactored - if possible have the casting refactored away into another method that handles casting dynamically on the fly based on fieldTypeName. Then it can cast expectedValue and givenValue to the correct types making the switch statement code less repetitive and have less duplication.

At compile time we have the values as strings and we have the type to CastTo as a string too. I am open to using the dynamic keyword here if someone is brave enough.

Naturally as more types are added to the DB the below switch statement is going to grow and break a few SOLID principles along the way.

private bool Run(string actionToApply, string fieldTypeName, string expectedValue, string givenValue)
{
    switch (actionToApply)
    {
        case "HasValue":
            return !string.IsNullOrWhiteSpace(givenValue) &amp;&amp; givenValue != expectedValue;

        case "EqualTo":
            return givenValue == expectedValue;

        case "NotEqualTo":
            return givenValue != expectedValue;

        case "Greater Than":
            if (fieldTypeName == "int")
            {
                var one = Convert.ToInt32(givenValue);
                var two = Convert.ToInt32(expectedValue);
                return one &gt; two;
            }
            if (fieldTypeName == "double")
            {
                var one = Convert.ToDouble(givenValue);
                var two = Convert.ToDouble(givenValue); 
                return one &gt; two;
            }
            return false;
        case "Or":
            var orArrayValues = expectedValue.Split(new[] { SplitOperatorForOr }, StringSplitOptions.None);
            return orArrayValues.Any(x =&gt; x == givenValue);
        case "Less Than":
            if (fieldTypeName == "int")
            {
                var one = Convert.ToInt32(givenValue);
                var two = Convert.ToInt32(expectedValue);
                return one &lt; two;
            }
            if (fieldTypeName == "double")
            {
                var one = Convert.ToDouble(givenValue);
                var two = Convert.ToDouble(givenValue);
                return one &lt; two;
            }
            return false;

        case "Range":
            var given = Convert.ToInt32(givenValue);
            var rangeArrayValues = expectedValue.Split(new[] { SplitOperatorForRange }, StringSplitOptions.None);
            if (fieldTypeName == "int")
            {
                var rangeA = (int)Convert.ChangeType(rangeArrayValues[0], typeof(int));
                var rangeB = (int)Convert.ChangeType(rangeArrayValues[1], typeof(int));
                return given &gt; rangeA &amp;&amp; given &lt; rangeB;
            }
            if (fieldTypeName == "double")
            {
                var rangeA = (double)Convert.ChangeType(rangeArrayValues[0], typeof(double));
                var rangeB = (double)Convert.ChangeType(rangeArrayValues[1], typeof(double));
                return given &gt; rangeA &amp;&amp; given &lt; rangeB;

            }
            return false;
    }
    return false;
}
Just a quick shot at case "Greater Than":  


case "Greater Than":
    if (fieldTypeName == "int")
    {
        var one = Convert.ToInt32(givenValue);
        var two = Convert.ToInt32(expectedValue);
        return one &gt; two;
    }
    if (fieldTypeName == "double")
    {
        var one = Convert.ToDouble(givenValue);
        var two = Convert.ToDouble(givenValue); 
        return one &gt; two;
    }
    return false;  



if fieldTypeName is double it is always returning false because copy&amp;pasta should be done carefully. This applies to Less Than as well.