using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace PushPlatform.Common.Util
{
    /// <summary>
    /// 表达式帮助类
    /// </summary>
    public class ExpressionHelper<T>
    {
        private object instance; //创建的实例化对象

        private MethodInfo method; //反射的方法

        #region 构造函数
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="expression">要计算的表达式</param>
        public ExpressionHelper(string expression)
        {
            if (expression.IndexOf("return") < 0)
                expression = "return " + expression;

            if (expression.IndexOf(";") < 0)
                expression += ";";

            string className = "ExpressionCalculate"; //类名称
            string methodName = "Calculate"; //执行的方法名称

            CompilerParameters p = new CompilerParameters();//动态编译参数
            p.GenerateInMemory = true; //在内存中生成

            CompilerResults cr = new CSharpCodeProvider().CompileAssemblyFromSource(p, string.
              Format("using System;sealed class {0}{{public {1} {2}(){{{3}}}}}",
              className, typeof(T).FullName, methodName, expression)); //初始化使用指定临时文件

            if (cr.Errors.Count > 0)
            {
                string msg = "Expression(" + expression + "): /n";

                foreach (CompilerError err in cr.Errors)
                    msg += err.ToString() + "/n";

                throw new Exception(msg);
            }

            instance = cr.CompiledAssembly.CreateInstance(className); //创建实例
            method = instance.GetType().GetMethod(methodName); //获取方法
        }
        #endregion

        #region 计算数据
        /// <summary>
        /// 计算数据
        /// </summary>
        /// <returns>返回计算值</returns>
        public double Calculate()
        {
            return (double)method.Invoke(instance, new object[] { }); //反射动态运行
        }
        #endregion

        #region 判断是否
        public bool Judge()
        {
            return (bool)method.Invoke(instance, new object[] { });
        }
        #endregion
    }
}
