//Creates a compute list with reference of indirect info to this list. public ComputeList Clone() { ComputeList computeList = new ComputeList(); return computeList; }
public void Optimize() { if (m_calculator == null) { System.Diagnostics.Debug.WriteLine("OptimizeManager.Optimize: m_calculator == null"); return; } //Contains dependices linked to expressions in calculator. Hashtable optimizables = new Hashtable(); // If FindDependices returns false, the key is marked as not-optimizable. Hashtable notOptimizables = new Hashtable(); //(28.07.2006 11:58) //Reduce unecessary calls to the property. m_functions = m_calculator.Functions; #region "Finding Dependicies" //Find all dependicies. Expression[] expressions = m_calculator.GetExpressions(); foreach (Expression exp in expressions) { ArrayList deps = new ArrayList(); // Get all the dependices of expression. // Use the variable name of expression key as relative. if (!FindDependices(exp.Key, exp.Tree, deps, exp.Key.Substring(0, exp.Key.IndexOf(Calculator.PROPERTY_CHAR)), null, false)) { // Mark as not optimizable. if (!notOptimizables.Contains(exp.Key)) { notOptimizables.Add(exp.Key, exp.Key); } } else { // Check for direct property dependence. object expObject = exp.Variable; if (expObject is IOptimizable) { IOptimizable expOpt = (IOptimizable)expObject; PropertyDependicy[] propDeps = expOpt.PropertyDependices; if (propDeps != null) { foreach (PropertyDependicy propDep in propDeps) { if (propDep.ParentProperty == exp.PropName) { deps.Add(exp.Variable.Name + Calculator.PROPERTY_CHAR + propDep.ChildProperty); } } } } if (deps.Count != 0) { DependicyInfo dependicy = new DependicyInfo(); dependicy.Key = exp.Key; //Analyse each dependicy. string[] depsTable = new string[deps.Count]; bool optimizable = true; for (int i = 0; i <= depsTable.Length - 1; i++) { string nodeValue = (string)deps[i]; if (!optimizables.Contains(nodeValue)) { //Create dependicy info. DependicyInfo depNode = new DependicyInfo(); depNode.Key = nodeValue; //Detect type. depNode.Type = DependicyType(nodeValue); //See if the dependicy is not optimizable. if (depNode.Type == DependicyInfo.DEPENDICY_TYPE_NOT_LEGAL) { optimizable = false; break; } else if (depNode.Type == DependicyInfo.DEPENDICY_TYPE_VARIABLE) { //See if variable inherits from IOptimizable. object obj = m_calculator.Variable(depNode.Key); if (!(obj is IOptimizable)) { optimizable = false; break; } } else if (depNode.Type == DependicyInfo.DEPENDICY_TYPE_PROPERTY) { //See if variable inherits from IOptimizable. int dotIndex = depNode.Key.IndexOf(Calculator.PROPERTY_CHAR); string varName = depNode.Key.Substring(0, dotIndex); object obj = m_calculator.Variable(varName); if (!(obj is IOptimizable)) { optimizable = false; break; } } //Add dependicy as optimizable. optimizables.Add(nodeValue, depNode); depsTable[i] = depNode.Key; } else { //Optimizable already exists. depsTable[i] = nodeValue; } } if (!optimizable) { notOptimizables.Add(exp.Key, exp.Key); } else { //Add as optimizable. dependicy.Type = DependicyInfo.DEPENDICY_TYPE_EXPRESSION; dependicy.Deps = depsTable; //Remove temporary optimizable. if (optimizables.Contains(exp.Key)) { optimizables.Remove(exp.Key); } optimizables.Add(exp.Key, dependicy); } } else { // Expression depends on no other. DependicyInfo dep = new DependicyInfo(); dep.Deps = new string[] {}; dep.Type = DependicyInfo.DEPENDICY_TYPE_EXPRESSION; dep.Key = exp.Key; // Remove temporary optimizable. if (optimizables.Contains(exp.Key)) { optimizables.Remove(exp.Key); } optimizables.Add(dep.Key, dep); } } } #endregion // Remove all not-optimizables from optimizables. foreach (string key in notOptimizables.Values) { if (optimizables.Contains(key)) { optimizables.Remove(key); } } //Remove all optimalizables that depends on not-optimalizables. Hashtable lastNotOptimizables = notOptimizables; //Continue to remove optimizables that depends on not-optimizables //until table of optimizables is clean. while (lastNotOptimizables.Count != 0) { //Find all optimizables that depends on newly removed optimizables. Hashtable tempNotOptimizables = new Hashtable(); foreach (DependicyInfo dep in optimizables.Values) { if (dep.Type == DependicyInfo.DEPENDICY_TYPE_EXPRESSION) { foreach (string depName in dep.Deps) { if (lastNotOptimizables[depName] != null) { tempNotOptimizables.Add(dep.Key, dep.Key); //Remove child property dependices of dependicy. int propIndex = depName.IndexOf(Calculator.PROPERTY_CHAR); string variableName = depName.Substring(0, propIndex); object obj = m_calculator.Variable(variableName); if (obj is IOptimizable) { IOptimizable opt = (IOptimizable)obj; if (opt.PropertyDependices != null) { foreach (PropertyDependicy propertyDep in opt.PropertyDependices) { if (propertyDep.ParentProperty == depName.Substring(propIndex + 1)) { string childKey = variableName + Calculator.PROPERTY_CHAR + propertyDep.ChildProperty; if (!tempNotOptimizables.Contains(childKey)) { tempNotOptimizables.Add(childKey, childKey); } } } } } break; } } } } //Remove from optimizables in end to not get enumeration exception. foreach (string expName in tempNotOptimizables.Values) { optimizables.Remove(expName); if (!notOptimizables.Contains(expName)) notOptimizables.Add(expName, expName); } lastNotOptimizables = tempNotOptimizables; } //Remove recursive. foreach (DependicyInfo opt in optimizables.Values) { SortedList history = new SortedList(); Hashtable processed = new Hashtable(optimizables.Count); RemoveRecursive(opt, optimizables, notOptimizables, history, processed); } //Remove all not-optimizables from optimizables. foreach (string key in notOptimizables.Values) { if (optimizables.Contains(key)) { optimizables.Remove(key); } } IVariable[] variables = m_calculator.GetVariables(); foreach (IVariable variable in variables) { if (variable is IOptimizable) { IOptimizable obj = (IOptimizable)variable; obj.PropertyChanged -= new PropertyChangedEventHandler(PropertyChanged); } } #region "Dependicy Reversing" //Build optimize graphs. //Reverse the dependices. Hashtable eventGraph = new Hashtable(); Hashtable objectMap = new Hashtable(); //(29.11.2006 12:15) Hashtable processedEvents = new Hashtable(); foreach (DependicyInfo opt in optimizables.Values) { if (opt.Deps != null) { AddToEventList(opt, opt.Deps, optimizables, eventGraph, objectMap, processedEvents); //An expression should update it self if it differ from it's previous value. if (opt.Type == DependicyInfo.DEPENDICY_TYPE_EXPRESSION) { string varName = opt.Key.Substring(0, opt.Key.IndexOf(Calculator.PROPERTY_CHAR)); object obj = m_calculator.Variable(varName); if (obj is IOptimizable) { IOptimizable optObj = (IOptimizable)obj; if (!eventGraph.Contains(opt.Key)) { if (!objectMap.Contains(optObj)) { optObj.PropertyChanged += new PropertyChangedEventHandler(PropertyChanged); objectMap.Add(optObj, varName); } eventGraph.Add(opt.Key, new ArrayList()); } //Add to event list. ArrayList events = (ArrayList)eventGraph[opt.Key]; if (!events.Contains(opt.Key)) { events.Add(m_calculator.GetExpressionObject(opt.Key)); } } } } } #endregion m_computeList = new ComputeList(); m_eventGraph = eventGraph; #region "Single Object Reference" //Single expressions using object references, are not necessary to compute. ArrayList objectReferences = new ArrayList(); foreach (string key in notOptimizables.Values) { string exp = m_calculator.GetExpression(key); if (exp != null && System.Text.RegularExpressions.Regex.IsMatch(exp.Trim(), Calculator.NAME_REGEX)) { objectReferences.Add(key); } } foreach (string key in objectReferences) { notOptimizables.Remove(key); } //Remember the object references for later use. m_objectReferences = objectReferences; //Create list of not optimizable expressions. ArrayList expressionList = new ArrayList(); foreach (string key in notOptimizables.Values) { Expression exp = m_calculator.GetExpressionObject(key); if (exp != null) { expressionList.Add(exp); } } #endregion m_notOptimizables = new Expression[expressionList.Count]; expressionList.CopyTo(m_notOptimizables); }