/// <summary> /// Return the value (using Reflection) of the specified property on the specified object. /// Returns null if not found. Examples of Names that can be found. /// Pod /// Environment.MeanT /// Organs[] /// Organs[AboveGround].Live /// Organs[AboveGround].Live.Wt /// Leaf.Leaves[Leaf.CurrentRank].CoverAbove /// Can return an Instance, an Entity or an object[] when an array specifier is present. /// </summary> public static object GetVariable(string NamePath, object RelativeTo) { Component My = null; if (RelativeTo is Component) { My = RelativeTo as Component; if ((My != null) && !NamePath.Contains("[")) { object v; My.GetObject(NamePath, out v); return(v); } } if (VarParts == null) { VarParts = new Dictionary <string, List <string> >(); } string[] Bits; //cache the list of names that are parsed here List <String> Parts; if (VarParts.TryGetValue(NamePath, out Parts)) { Bits = Parts.ToArray(); } else { Bits = StringManip.SplitStringHonouringBrackets(NamePath, '.', '[', ']'); VarParts.Add(NamePath, Bits.ToList()); } for (int i = 0; i < Bits.Length; i++) { string ArraySpecifier = ""; bool ArrayFound = Bits[i].Contains("["); if (ArrayFound) { ArraySpecifier = StringManip.SplitOffBracketedValue(ref Bits[i], '[', ']'); } object MatchingChild; if (RelativeTo is Component) { MatchingChild = (RelativeTo as Component).LinkByName(Bits[i]); // Try for a model name first. e.g. Root if (MatchingChild == null) { (RelativeTo as Component).GetObject(Bits[i], out MatchingChild); // may be a variable. e.g. Organs } } else { MatchingChild = Utility.GetValueOfFieldOrProperty(Bits[i], RelativeTo); } if (MatchingChild == null) { throw new Exception("Cannot find variable: " + NamePath); } // Look for array spec if (ArrayFound) { if (!(MatchingChild is IList)) { throw new Exception("Cannot specify an array on a non array variable. Name: " + NamePath); } IList Array = MatchingChild as IList; // First try and treat the ArraySpecifier as an integer index. // If that's not possible, then assume it is a reference to an integer variable // somewhere in the system. // If that's not possible then assume it is a type name e.g. AboveGround. int ArrayIndex; bool ok = int.TryParse(ArraySpecifier, out ArrayIndex); if (ArraySpecifier != "" && !ok && My != null) { object ArraySpec; ok = My.GetObject(ArraySpecifier, out ArraySpec); // Assume it is a simulation variable. if (ok && (ArraySpec is Int32 || ArraySpec is Double)) { ArrayIndex = Convert.ToInt32(ArraySpec); } else { ok = false; } } if (ok) { if (ArrayIndex < 0 || ArrayIndex >= Array.Count) { throw new Exception("Invalid index of " + ArrayIndex.ToString() + " found while indexing into variable: " + NamePath); } MatchingChild = Array[ArrayIndex]; } else { // Must be a type name. Go collect an array of objects of that type. List <object> ArrayOfType = new List <object>(); // Construct a name remainder. string RestOfName = null; for (int j = i + 1; j < Bits.Length; j++) { if (RestOfName != null) { RestOfName += "."; } RestOfName += Bits[j]; } foreach (object o in Array) { if (ArraySpecifier == "" || Utility.IsOfType(o.GetType(), ArraySpecifier)) { if (RestOfName == null) { ArrayOfType.Add(o); } else { object ChildObject = GetVariable(RestOfName, o); // recursion if (ChildObject != null) { ArrayOfType.Add(ChildObject); } } } } return(ArrayOfType.ToArray()); } } RelativeTo = MatchingChild; } // If we get this far then we've found a match. return(RelativeTo); }