/// <summary> /// Performs a getall command for a given class and property, and returns /// a dictionary with the property values keyed by their objects. /// </summary> /// <param name="className">The name of the class to retreive each object for.</param> /// <param name="property">The property to retreive for each object.</param> /// <returns> /// A dictionary in which objects of the class key their value for the /// specified property. If the property contains a singular value, the /// value is a string. If it contains an array, the value is an /// IReadOnlyList<string>. /// </returns> /// public static IReadOnlyDictionary <BLObject, object> GetAll(string className, string property) { // Create the dictionary we will return. var results = new Dictionary <BLObject, object>(); // Run the getall command. If this fails, return the empty results. var output = RunCommand("getall {0} {1}", className, property); if (output == null) { return(results); } // getall results should be in the following format: // <index>) <subclass> <object>.<property> = <value> // Or, if the result's property is an array: // <index>) <subclass> <object>.<property> = Regex objectPattern = new Regex($@"^\d+\) ([^ ]+) (.+)\.{Regex.Escape(property)} =( ?)(.*)$", RegexOptions.Compiled); // The current object and array we are working with. BLObject objectKey = null; List <object> arrayValue = null; // Iterate over each line of output. foreach (string line in output) { // The match for if we test a line for an object result. Match objectMatch; // If we are currently working with an array as an object's value, // we will test the current line for its membership. if (arrayValue != null) { // Check that the current line is of the format for a member of // an array value. var memberMatch = _MemberPattern.Value.Match(line); if (memberMatch.Success) { object value = BLIO.Parse(memberMatch.Groups[1].Value); // If it is, add the captured value to the array, and // proceed on to the next line. arrayValue.Add(value); continue; } // If the line is not a member of the array, check whether it is // of the format denoting a new object. objectMatch = objectPattern.Match(line); if (objectMatch.Success) { // If it is, this indicates the working array value was // complete, so associate with the working object, and null // it to indicate we're no longer working with an array. results[objectKey] = arrayValue; arrayValue = null; } } else { // If we are not currently working with an array, check whether // the line is of the format denoting a new object. If not, skip // this line and proceed to the next one. objectMatch = objectPattern.Match(line); if (!objectMatch.Success) { continue; } } // By now we have a match for an object declaration. Extract the // name and class name from it, and create a new object accordingly. string subclassName = objectMatch.Groups[1].Value; string objectName = objectMatch.Groups[2].Value; objectKey = new BLObject(objectName, subclassName); // If the value capture group for the match did capture, associate // the object with the value. if (objectMatch.Groups[3].Value.Length == 1) { results[objectKey] = BLIO.Parse(objectMatch.Groups[4].Value); } // Otherwise, we are to expect an array as the value, so create a // new list for indicating such and for storing the results. else { arrayValue = new List <object>(); } } // At the end of the results, if we had a working array value, // associate with the working object. if (arrayValue != null) { results[objectKey] = arrayValue; } return(results); }