Beispiel #1
0
        /// <summary>
        /// 计算表达式字典
        /// </summary>
        /// <param name="strFuncName"></param>
        /// <param name="arrParams"></param>
        /// <param name="calcContext"></param>
        /// <returns></returns>
        private static object CalculateExpressionDictionary(string strFuncName, ParamObjectCollection arrParams, CalculateContext calcContext)
        {
            ExpressionDictionaryCollection dictionaries = (ExpressionDictionaryCollection)ObjectContextCache.Instance.GetOrAddNewValue(
                "ExpressionDictionaries",
                (cache, key) =>
            {
                ExpressionDictionaryCollection expDicts = new ExpressionDictionaryCollection();

                expDicts.InitFromConfiguration(ExpressionDictionarySettings.GetConfig());

                cache.Add("ExpressionDictionaries", expDicts);

                return(expDicts);
            });

            ExpressionDictionary dictionary = dictionaries[strFuncName];

            object oValue = null;

            if (dictionary != null)
            {
                ExpressionDictionaryCalculatorContext context = new ExpressionDictionaryCalculatorContext(dictionary, calcContext.CallerContxt);

                string key = string.Empty;

                if (arrParams.Count > 0 && arrParams[0].Value != null)
                {
                    key = arrParams[0].Value.ToString();
                }

                oValue = dictionary.Calculator.Calculate(strFuncName, key, context);
            }

            return(oValue);
        }
        private object[] PrepareParameters(IList <ParameterInfo> methodParams, ParamObjectCollection arrParams, object callerContext)
        {
            object[] result = new object[methodParams.Count];

            for (int i = 0; i < arrParams.Count; i++)
            {
                ParameterInfo pi = methodParams[i];

                try
                {
                    result[i] = DataConverter.ChangeType(arrParams[i].Value, pi.ParameterType);
                }
                catch (System.Exception ex)
                {
                    throw new InvalidCastException(string.Format("内置函数{0}参数{1}类型转换错误。{2}",
                                                                 this.FunctionName, pi.Name, ex.Message), ex);
                }
            }

            //如果方法的参数比表达式的参数多一个,则将调用上下文作为最后一个参数
            if (result.Length == arrParams.Count + 1)
            {
                result[arrParams.Count] = callerContext;
            }

            return(result);
        }
        /// <summary>
        /// 执行方法
        /// </summary>
        /// <param name="target"></param>
        /// <param name="arrParams"></param>
        /// <param name="callerContext"></param>
        /// <returns></returns>
        public object ExecuteFunction(object target, ParamObjectCollection arrParams, object callerContext)
        {
            ParameterInfo[] methodParams = this.MethodInfo.GetParameters();

            CheckParametersCount(methodParams, arrParams);

            return(this.MethodInfo.Invoke(target, PrepareParameters(methodParams, arrParams, callerContext)));
        }
        /// <summary>
        /// 执行静态函数
        /// </summary>
        /// <param name="funcName"></param>
        /// <param name="type"></param>
        /// <param name="arrParams"></param>
        /// <param name="callerContext"></param>
        /// <returns></returns>
        public static object ExecuteFunction(string funcName, Type type, ParamObjectCollection arrParams, object callerContext)
        {
            type.NullCheck("type");

            BuiltInFunctionInfoCollection funcsInfo = GetBuiltInFunctionsInfo(type);

            object result = null;

            if (funcsInfo.Contains(funcName))
            {
                result = funcsInfo[funcName].ExecuteFunction(null, arrParams, callerContext);
            }

            return(result);
        }
        /// <summary>
        /// 执行函数
        /// </summary>
        /// <param name="funcName"></param>
        /// <param name="target"></param>
        /// <param name="arrParams"></param>
        /// <param name="callerContext"></param>
        /// <returns></returns>
        public static object ExecuteFunction(string funcName, object target, ParamObjectCollection arrParams, object callerContext)
        {
            target.NullCheck("target");

            BuiltInFunctionInfoCollection funcsInfo = GetBuiltInFunctionsInfo(target.GetType());

            object result = null;

            if (funcsInfo.Contains(funcName))
            {
                result = funcsInfo[funcName].ExecuteFunction(target, arrParams, callerContext);
            }

            return(result);
        }
Beispiel #6
0
        public object GetUserFunctionValue(string strFuncName, ParamObjectCollection arrParams)
        {
            object oValue = null;

            if (this.CalculateUserFunction != null)
            {
                oValue = this.CalculateUserFunction(strFuncName, arrParams, this.CallerContxt);
            }
            else
            if (this.BuiltInFunctionsWrapper != null)
            {
                oValue = BuiltInFunctionHelper.ExecuteFunction(strFuncName, this.BuiltInFunctionsWrapper, arrParams, this.CallerContxt);
            }

            return(oValue);
        }
Beispiel #7
0
        private static object DoDateDiff(ParamObjectCollection arrParams)
        {
            arrParams.CheckParamsLength(3);
            arrParams[0].CheckParameterType <string>();
            arrParams[1].CheckParameterType <DateTime>();
            arrParams[2].CheckParameterType <DateTime>();

            DateTime startTime = (DateTime)arrParams[1].Value;
            DateTime endTime   = (DateTime)arrParams[2].Value;

            TimeSpan ts = endTime - startTime;

            double result = 0;

            string intervalType = arrParams[0].Value.ToString().ToLower();

            switch (intervalType)
            {
            case "d":
                result = ts.TotalDays;
                break;

            case "h":
                result = ts.TotalHours;
                break;

            case "n":
                result = ts.TotalMinutes;
                break;

            case "s":
                result = ts.TotalSeconds;
                break;

            case "ms":
                result = ts.TotalMilliseconds;
                break;

            default:
                throw new SystemSupportException(string.Format(ExpressionParserRes.InvalidDateDiffType, intervalType));
            }

            return(Math.Ceiling(Convert.ToDecimal(result)));
        }
Beispiel #8
0
        private static object DoInFunction(ParamObjectCollection arrParams, CalculateContext calcContext)
        {
            bool result = false;

            if (arrParams.Count > 0)
            {
                object sourceData = arrParams[0].Value;

                for (int i = 1; i < arrParams.Count; i++)
                {
                    if ((bool)CompareEqualOP(sourceData, arrParams[i].Value, 0))
                    {
                        result = true;
                        break;
                    }
                }
            }

            return(result);
        }
Beispiel #9
0
        private object VExp(ExpTreeNode node, CalculateContext calcContext)
        {
            object oValue = null;

            if (node != null)
            {
                try
                {
                    switch (node.OperationID)
                    {
                    case Operation_IDs.OI_NUMBER:
                    case Operation_IDs.OI_STRING:
                    case Operation_IDs.OI_NEG:
                    case Operation_IDs.OI_BOOLEAN:
                    case Operation_IDs.OI_DATETIME:
                        oValue = node.Value;
                        break;

                    case Operation_IDs.OI_ADD:
                        oValue = AddOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position);
                        break;

                    case Operation_IDs.OI_MINUS:
                    {
                        object p1 = VExp(node.Left, calcContext);
                        object p2 = VExp(node.Right, calcContext);

                        CheckOperandNull(p1, p2, node.Position);
                        oValue = NToD(p1) - NToD(p2);
                    }
                    break;

                    case Operation_IDs.OI_MUL:
                    {
                        object p1 = VExp(node.Left, calcContext);
                        object p2 = VExp(node.Right, calcContext);

                        CheckOperandNull(p1, p2, node.Position);
                        oValue = NToD(p1) * NToD(p2);
                    }
                    break;

                    case Operation_IDs.OI_DIV:
                    {
                        object p1 = VExp(node.Left, calcContext);
                        object p2 = VExp(node.Right, calcContext);

                        CheckOperandNull(p1, p2, node.Position);

                        if (NToD(p2) == 0.0M)
                        {
                            throw ParsingException.NewParsingException(ParseError.peFloatOverflow, node.Position);
                        }

                        oValue = NToD(p1) / NToD(p2);
                    }
                    break;

                    case Operation_IDs.OI_LOGICAL_OR:
                    {
                        oValue = (bool)VExp(node.Left, calcContext);
                        object oRight = (bool)false;

                        if ((bool)oValue == false)
                        {
                            oRight = VExp(node.Right, calcContext);
                        }

                        CheckOperandNull(oValue, oRight, node.Position);
                        oValue = (bool)oValue || (bool)oRight;
                    }
                    break;

                    case Operation_IDs.OI_LOGICAL_AND:
                    {
                        oValue = (bool)VExp(node.Left, calcContext);
                        object oRight = (bool)true;

                        if ((bool)oValue == true)
                        {
                            oRight = VExp(node.Right, calcContext);
                        }

                        CheckOperandNull(oValue, oRight, node.Position);
                        oValue = (bool)oValue && (bool)oRight;
                    }
                    break;

                    case Operation_IDs.OI_NOT:
                        oValue = VExp(node.Right, calcContext);
                        CheckOperandNull(oValue, node.Position);
                        oValue = !(bool)oValue;
                        break;

                    case Operation_IDs.OI_GREAT:
                        oValue = CompareGreatOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position);
                        break;

                    case Operation_IDs.OI_GREATEQUAL:
                        oValue = CompareGreatEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position);
                        break;

                    case Operation_IDs.OI_LESS:
                        oValue = CompareLessOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position);
                        break;

                    case Operation_IDs.OI_LESSEQUAL:
                        oValue = CompareLessEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position);
                        break;

                    case Operation_IDs.OI_NOT_EQUAL:
                        oValue = CompareNotEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position);
                        break;

                    case Operation_IDs.OI_EQUAL:
                        oValue = CompareEqualOP(VExp(node.Left, calcContext), VExp(node.Right, calcContext), node.Position);
                        break;

                    case Operation_IDs.OI_USERDEFINE:
                    {
                        oValue = CalculateFunction(node, node.Params, calcContext);

                        if (oValue == null)
                        {
                            ParamObjectCollection funcParams = GetParams(node.Params, calcContext);

                            oValue = CalculateFunctionWithParameters(node.FunctionName, funcParams, calcContext);

                            if (oValue == null)
                            {
                                oValue = calcContext.GetUserFunctionValue(node.FunctionName, funcParams);
                            }

                            if (oValue == null)
                            {
                                oValue = CalculateExpressionDictionary(node.FunctionName, funcParams, calcContext);
                            }
                        }
                    }
                    break;

                    default:
                        throw ParsingException.NewParsingException(
                                  ParseError.peInvalidOperator,
                                  node.Position,
                                  EnumItemDescriptionAttribute.GetAttribute(node.OperationID).ShortName);
                    }
                }
                catch (System.InvalidCastException)
                {
                    throw ParsingException.NewParsingException(ParseError.peTypeMismatch, node.Position);
                }
            }

            return(oValue);
        }
Beispiel #10
0
        /// <summary>
        /// 计算所有参数都已经准备好了的函数
        /// </summary>
        /// <param name="strFuncName"></param>
        /// <param name="arrParams"></param>
        /// <param name="calcContext"></param>
        /// <returns></returns>
        private static object CalculateFunctionWithParameters(string strFuncName, ParamObjectCollection arrParams, CalculateContext calcContext)
        {
            object oValue = null;

            try
            {
                switch (strFuncName.ToLower())
                {
                case "now":
                    oValue = DateTime.Now;
                    break;

                case "today":
                    oValue = DateTime.Today;
                    break;

                case "dateinterval.day":
                    oValue = "d";
                    break;

                case "dateinterval.hour":
                    oValue = "h";
                    break;

                case "dateinterval.minute":
                    oValue = "n";
                    break;

                case "dateinterval.second":
                    oValue = "s";
                    break;

                case "dateinterval.millisecond":
                    oValue = "ms";
                    break;

                case "datediff":
                    oValue = DoDateDiff(arrParams);
                    break;

                case "mindate":
                    oValue = DateTime.MinValue;
                    break;

                case "maxdate":
                    oValue = DateTime.MaxValue;
                    break;
                    //default:
                    //    {
                    //        if (calcContext.CalculateUserFunction != null)
                    //            oValue = calcContext.CalculateUserFunction(strFuncName, arrParams, calcContext.CallerContxt);

                    //        break;
                    //    }
                }

                return(oValue);
            }
            catch (ParsingException)
            {
                throw;
            }
            catch (System.Exception ex)
            {
                throw new SystemSupportException(string.Format(ExpressionParserRes.FunctionError, strFuncName, ex.Message));
            }
        }
 private static void CheckParametersCount(ParameterInfo[] methodParams, ParamObjectCollection arrParams)
 {
     (methodParams.Length == arrParams.Count || methodParams.Length == arrParams.Count + 1).FalseThrow <ArgumentOutOfRangeException>(
         "内置的表达式方法的参数是{0}个,而调用参数是{1}个,不匹配", methodParams.Length, arrParams.Count);
 }