Friday, April 15, 2011

Convert complex bool condition from string to bool in .NET

I need to parse complex expresion from string to bool.

It can only contain:
* boolean values (true/false),
* parenthesis,
* AND/OR operands (&&, ||)

Eg:

bool.Parse("((true || false) && (false || false)) || (true || false)"

Any idea how to achieve this?

From stackoverflow
  • The standard method is to:

    • tokenize the string
    • build a tree putting an operator in every node and an operand in every leaf
    • visiting the tree evaluating the expression
  • Here's a cunning evaluator class that gives you the JScript.NET Eval function within C# code:

    static public class Evaluator
    {
        private const string _jscriptSource =
            @"package Evaluator
            {
               class Evaluator
               {
                  public function Eval(expr : String) : String 
                  { 
                     return eval(expr); 
                  }
               }
            }";
    
        static private object _evaluator;
        static private Type _evaluatorType;
    
        [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline",
            Justification = "Can't be done inline - too complex")]
        static Evaluator()
        {
            InstantiateInternalEvaluator();
        }
    
        static private void InstantiateInternalEvaluator()
        {
            JScriptCodeProvider compiler = new JScriptCodeProvider();
    
            CompilerParameters parameters;
            parameters = new CompilerParameters();
            parameters.GenerateInMemory = true;
    
            CompilerResults results;
            results = compiler.CompileAssemblyFromSource(parameters, _jscriptSource);
    
            Assembly assembly = results.CompiledAssembly;
            _evaluatorType = assembly.GetType("Evaluator.Evaluator");
    
            _evaluator = Activator.CreateInstance(_evaluatorType);
        }
    
        static public int EvaluateToInteger(string statement)
        {
            string s = EvaluateToString(statement);
            return int.Parse(s);
        }
    
        static public double EvaluateToDouble(string statement)
        {
            string s = EvaluateToString(statement);
            return double.Parse(s);
        }
    
        static public decimal ForceEvaluateToDecimal(string statement)
        {
            decimal result;
            bool s = Decimal.TryParse(statement, out result);
            return result;
        }
    
        static public decimal EvaluateToDecimal(string statement)
        {
            string s = EvaluateToString(statement);
            return decimal.Parse(s);
        }
    
        static public string EvaluateToString(string statement)
        {
            object o = EvaluateToObject(statement);
            return o.ToString();
        }
    
        static public bool EvaluateToBool(string statement)
        {
            object o = EvaluateToObject(statement);
            return (bool)o;
        }
    
        static public object EvaluateToObject(string statement)
        {
            try
            {
                return _evaluatorType.InvokeMember(
                    "Eval",
                    BindingFlags.InvokeMethod,
                    null,
                    _evaluator,
                    new object[] {statement}
                    );
            }
            catch (Exception)
            {
                InstantiateInternalEvaluator();
                return null;
            }
        }
    }
    

    You just then call Evaluator.EvaluateToBool(string). Lifted from an existing project, so you may want to tweak!

    Maciej : awesome! PS EvaluateToBool shall has bool return
    Maciej : BTW How about performance? Do you think this can be an issue?
    David M : "Maciej (first comment) - schoolboy copy, paste and fail to edit properly error. Will edit. Thanks.
  • The string you described is valid C# code, so if you can interpret it at runtime you're done. In many languages this is a built in function. In C# it is not, but you can use a 3rd party library such as this runtime C# interpreter

    Maciej : Runtime C# Expression Evaluator you mentioned looks interesting but download link seems be broken- do you have source ?
    Maciej : Sorry - started working now

0 comments:

Post a Comment