表达式计算 DataTable/DataRow/DataColumn Expression、JScript CodeDomProvider Eval


namespace ConsoleApplication
{
    using System;
    using System.Linq;
    using System.Reflection;
    using System.Collections.Generic;
    using Microshaoft;
    public class Class1
    {
        static void Main(string[] args)
        {
            string formula = "(({0}-{1})/{2}+{3})*{4}";
            string result = JScriptEvaluator.ComputeFormula<double>
                                                    (
                                                        formula
                                                        , 1f
                                                        , 2.1
                                                        , 3.1
                                                        , 4.0
                                                        , 5.0
                                                    );
            Console.WriteLine(result);
            double x;
            x = DataTableColumnExpression.ComputeFormula<double, double>
                                                    (
                                                        formula
                                                        , 1f
                                                        , 2.1
                                                        , 3.1
                                                        , 4.0
                                                        , 5.0
                                                    );
            Console.WriteLine(x);
            //=================================================================================================
            formula = "IIF(1=2, F1, F2) + ((--F1) * F2) + F3";
            Dictionary<string, int> dict = new Dictionary<string, int>();
            dict.Add("F1", 2);
            dict.Add("F2", 3);
            dict.Add("F3", 4);
            x = DataTableColumnExpression.ComputeFormula<double, int>(formula, dict);
            Console.WriteLine(x);
            Console.ReadLine();
        }
    }
}
namespace Microshaoft
{
    using System;
    using System.Data;
    using System.Linq;
    using System.Collections.Generic;
    using System.Reflection;
    using System.CodeDom.Compiler;
    public class DataTableColumnExpression
    {
        private static MethodInfo _mi = typeof(string).GetMethods().First
                                                                    (
                                                                        m => m.Name.Equals("Format")
                                                                        && m.GetParameters().Length == 2
                                                                        && m.IsStatic
                                                                        && m.GetParameters()[1].Name == "args"
                                                                    );
        public static TResult ComputeFormula<TResult, TParameter>(string formula, params TParameter[] parameters)
        {
            var dt = new DataTable();
            var list = parameters.ToList();
            var parametersName = new List<string>(); ;
            int i = 0;
            list.ForEach
                    (
                        parameter =>
                        {
                            //string f = string.Format("{{{0}}}", i++);
                            string f = string.Format("F{0}", i++);
                            parametersName.Add(f);
                            var dc = new DataColumn(f, typeof(TParameter));
                            dt.Columns.Add(dc);
                        }
                    );
            object[] ps = new object[parameters.Length];
            Array.Copy(parametersName.ToArray(), 0, ps, 0, ps.Length);
            string expression = (string) _mi.Invoke
                                                (
                                                    null
                                                    , new object[]
                                                            {
                                                                formula
                                                                , ps
                                                            }
                                                );
            dt.Columns.Add(new DataColumn("Microshaoft", typeof(TResult), expression));
            var dr = dt.NewRow();
            i = 0;
            list.ForEach
                    (
                        parameter =>
                        {
                            dr[i++] = parameter;
                        }
                    );
            dt.Rows.Add(dr);
            return (TResult) dr["Microshaoft"];
        }
        public static TResult ComputeFormula<TResult, TParameter>(string formula, IDictionary<string, TParameter> parameters)
        {
            var dt = new DataTable();
            var list = parameters.ToList();
            list.ForEach
                    (
                        kvp =>
                        {
                            var dc = new DataColumn(kvp.Key, typeof(TParameter));
                            dt.Columns.Add(dc);
                        }
                    );
            dt.Columns.Add(new DataColumn("Microshaoft", typeof(TResult), formula));
            var dr = dt.NewRow();
            list.ForEach
                    (
                        kvp =>
                        {
                            dr[kvp.Key] = kvp.Value;      
                        }
                    );
            dt.Rows.Add(dr);
            return (TResult) dr["Microshaoft"];
        }
    }
    public class JScriptEvaluator
    {
        private static MethodInfo _mi = typeof(string).GetMethods().First
                                                                        (
                                                                            m => m.Name.Equals("Format")
                                                                            && m.GetParameters().Length == 2
                                                                            && m.IsStatic
                                                                            && m.GetParameters()[1].Name == "args"
                                                                        );
        public static string ComputeFormula<TParameter>(string formula, params TParameter[] parameters)
        {
            object[] ps = new object[parameters.Length];
            Array.Copy(parameters.ToArray(), 0, ps, 0, ps.Length);
            string expression = (string) _mi.Invoke
                                                (
                                                    null
                                                    , new object[]
                                                            {
                                                                formula
                                                                , ps
                                                            }
                                                );
            return (string) JScriptEvaluator.Eval(expression);
        }
        public static object Eval(string statement)
        {
            return _evaluatorType.InvokeMember
                                        (
                                            "Eval"
                                            , BindingFlags.InvokeMethod
                                            , null
                                            , _evaluator
                                            , new object[]
                                                    {
                                                        statement
                                                    }
                                        );
        }
        static JScriptEvaluator()
        {
            CodeDomProvider provider = CodeDomProvider.CreateProvider("JScript");
            CompilerParameters parameters;
            parameters = new CompilerParameters();
            parameters.GenerateInMemory = true;
            CompilerResults results;
            results = provider.CompileAssemblyFromSource(parameters, _JScript);
            Assembly assembly = results.CompiledAssembly;
            _evaluatorType = assembly.GetType("Microshaoft.JScriptEvaluator");
            _evaluator = Activator.CreateInstance(_evaluatorType);
        }
        private static object _evaluator = null;
        private static Type _evaluatorType = null;
        /// <summary>
        /// JScript代码
        /// </summary>
        private static readonly string _JScript =
            @"
                package Microshaoft
                {
                    class JScriptEvaluator
                    {
                        public function Eval(statement : String) : String
                        {
                            return eval(statement);
                        }
                    }
                }
            ";
    }
}

posted @ 2012-03-01 20:38  于斯人也  阅读(573)  评论(0编辑  收藏  举报