public SubExpressionUpdate(ICalculator calculator, IFunction callFunction, string val, int propIndex, IVariable relative) { if (propIndex == -1 && callFunction is IVariableReferencePropertyUsage) { if (val != relative.Name) { // Compute dependicy properties before returning the variable // in order to receive correct values. object var = calculator.ComputeVariable(val, null); string[] props = ((IVariableReferencePropertyUsage)callFunction).GetDependices(var.GetType()); if (props != null) { foreach (string prop in props) { Expression exp = calculator.GetExpressionObject(val + "." + prop); if (exp != null) m_expressionList.Add(exp); } } } } else if (propIndex > 0) { // Compute property dependices before this. string name = val.Substring(0, propIndex); if (name != relative.Name) { object var = calculator.ComputeVariable(name, null); if (var is IOptimizable) { IOptimizable opt = (IOptimizable)var; PropertyDependicy[] deps = opt.PropertyDependices; string prop = val.Substring(propIndex + 1); if (deps != null) { Expression[] exps = new Expression[1]; foreach (PropertyDependicy dep in deps) { if (dep.ParentProperty == prop) { Expression exp = calculator.GetExpressionObject(name + "." + dep.ChildProperty); if (exp != null) m_expressionList.Add(exp); } } } } } } }
//Calculates the value by expression tree. //Calculator - The object that contains functions, variables and expressions. //Relative - The relative variable. public object Calc(ICalculator calculator, IVariable relative, IFunction callFunction) { try { if (m_type == NODE_TYPE.FUNCTION || m_type == NODE_TYPE.OPERATOR) { //Run function. IFunction func; //(14.11.2006 11:50) //Point directly to the function to increase speed. if (m_function != null) { func = m_function; } else { string val = (string)m_value; FunctionSet functions = calculator.Functions; if (functions.Contains(val)) { func = functions.Item(val); m_function = func; } else { throw new Exception("Unknown function :" + val); } } if (func is IIntelligenceFunction) { return ((IIntelligenceFunction)func).Run(m_subNodes, calculator, relative); } object[] @params = new object[this.m_subNodes.Length]; //The argument position. int i = 0; while (i < @params.Length) { object obj = m_subNodes[i].Calc(calculator, relative, func); @params[i] = obj; i += 1; } return func.Run(@params); } else if (m_type == NODE_TYPE.TEXT) return m_value; else if (m_type == NODE_TYPE.NUMBER) return (float)m_value; else if (m_type == NODE_TYPE.VARIABLE) { string val = (string)m_value; int propIndex = val.IndexOf('.'); #region "Sub Expression Updating" // Update sub expressions before calculating the value to make sure // the computation will be correct. if (calculator.RunExpressions && relative != null) { if (this.m_subExpressionUpdate == null) this.m_subExpressionUpdate = new SubExpressionUpdate(calculator, callFunction, val, propIndex, relative); this.m_subExpressionUpdate.UpdateSubExpressions(calculator); if (propIndex == 0) return relative.GetType().InvokeMember(val.Substring(propIndex + 1), System.Reflection.BindingFlags.GetProperty, null, relative, new object[] {}); else return calculator.ComputeVariable(val, null); } #endregion // Don't use relative if there is none. if (relative == null || propIndex != 0 && (propIndex == -1 || val.Substring(0, propIndex) != relative.Name)) { return calculator.ComputeVariable(val, relative); } // Get value directly from variable if relative is the variable. return relative.GetType().InvokeMember(val.Substring(propIndex + 1), System.Reflection.BindingFlags.GetProperty, null, relative, new object[] {}); } } catch (Exception ex) { if (!(ex is ExpressionException)) { throw new ExpressionException(ex.Message, m_column, m_length); } else { throw ex; } } return null; }