Monday, October 2, 2006

3062.aspx

How to implement a JavaScript eval function in c#

I recently needed a javascript like eval() function for a .NET project. I didn't feel like porting JPLite so I googled a bit until I found this gem that saved my day: An Eval Function for C# using JScript.NET (JavaScript)


It shows how to use the out of the box .NET libraries to implement a eval() function using JScript.NET. The code works but it is not thread safe. With some minor adjustments you get this neat boolean evaluator function (comments and error management removed to save space):



using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.JScript;
 
namespace  JavaScript
{    public class Evaluator
    {
        private static Type _evaluatorType = null;
        private static readonly string _jscriptSource = 
            @"package Evaluator
                {
                    class Evaluator
                    {
                        public function Eval(expr : String) : String 
                        { 
                            return eval(expr); 
                        }
                    }
                }";
 
        static Evaluator()
        {
            ICodeCompiler compiler;
            compiler = new JScriptCodeProvider().CreateCompiler();
 
            CompilerParameters parameters;
            parameters = new CompilerParameters();
            parameters.GenerateInMemory = true;
 
            CompilerResults results;
            results = compiler.CompileAssemblyFromSource(parameters, 
                                 _jscriptSource);
 
            Assembly assembly = results.CompiledAssembly;
            _evaluatorType = assembly.GetType("Evaluator.Evaluator");
 
        }
 
        // ...
        public static bool EvalToBoolean(string statement)
        {
            string s = EvalToString(statement);
            return bool.Parse(s);
        }
 
        public static string EvalToString(string statement)
        {
            object o = EvalToObject(statement);
            return o.ToString();
        }
 
        public static object EvalToObject(string statement)
        {
            object evaluator = Activator.CreateInstance(_evaluatorType);
            return _evaluatorType.InvokeMember("Eval", 
                    BindingFlags.InvokeMethod, null, evaluator, new object[] 
                                                          { statement } );                
        }
    }
}




Example usage:


System.Console.Out.WriteLine("1==1 : {0}", 
        JavaScript.Evaluator.EvalToBoolean("1==1"));
System.Console.Out.WriteLine("'abcd'.indexOf('c') : {0}", 
        JavaScript.Evaluator.EvalToString("'abc'.indexOf('c')"));

Output:


1==1 : True
'abcd'.indexOf('c') : 2


I spend most of my time working with Java these days and I keep banging my head against the wall regarding the a lack of decent multi-threading features. It is true that there are a lot of open source libraries out there that helps but why re-invent the wheel or go crazy integrating 3rd party libraries when you get all the features you need out of the box? Don't get me wrong; I have a lot of fun with Java but once in a while I miss my C#...


(Edited for layout issues on small screens)

3 comments:

  1. When I try this code I get an error on

    using Microsoft.JScript;



    The type or namespace name 'JScript' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)

    ReplyDelete
  2. Sorry, I forgot to add one important step.



    You must add a reference to "Microsoft.JScript".

    ReplyDelete
  3. Thanks Egil. It's all good.

    ReplyDelete