--EDIT-- Rewritten to better clarify what I am trying to do, and what the problem is. Apologies that it is not succinct, but the context may help with the understanding.
I have a program where I run a number of simulations, against various scenarios. I store the results of these simulations and scenarios in a class ("Results class"), with the basic results stored as properties of the class, and the various scenarios and sensitivities stored in dictionaries within the class.
Because different users will want different outputs from the simulations, I am trying to develop a means of allowing users to generate custom reports. To do this, I am using reflection. I use reflection to work through each Property in the Results class, and add it to a treeview, using the same hierarchy as the Report Class. The user can then browse the treeview, see each property, and select the ones that they want in their report.
When the user selects a property to report, I use the tree hierarchy to turn this into a "path" - a delimited string that describes the property branch to the item of interest: eg:
Results.TotalCapacity; or:
Results.UsableCapacity; or
Results.Scenarios[HighCase].TotalCapacity; or
Results.Sensitivity.ModifiedCapacity.
Ultimately, I want to use reflection to parse these paths, and retrieve the values from them.
I borrowed code heavily from this link, but am struggling with the best way to retrieve the appropriate object when one of the objects in the path is a dictionary.
I have managed to get this to work, but I'd appreciate any feedback as to how it can be improved or made more robust. Casting the dictionary to a list and then grabbing the key via an index is clearly not optimum. I can modify my 'path' code to return the dictionary key, but not sure how to get the dictionary value from the key using reflection.
Code as follows:
public object GetPropertyValueFromPath(object baseObject, string path)
{
//Split into the base path elements
string[] pp = CorrectPathForDictionaries(path).Split(new[]{ '.' }, StringSplitOptions.RemoveEmptyEntries);
//Set initial value of the ValueObject
object valueObject = baseObject;
foreach (var prop in pp)
{
if (prop.Contains("["))
{
//Will be a dictionary. Get the name of the dictionary, and the index element of interest:
string dictionary = prop.Substring(0, prop.IndexOf("["));
int index = Convert.ToInt32(prop.Substring(prop.IndexOf("[") + 1, prop.Length - prop.IndexOf("]")));
//Get the property info for the dictionary
PropertyInfo dictInfo = valueObject.GetType().GetProperty(dictionary);
if (dictInfo != null)
{
//Get the dictionary from the PropertyInformation
valueObject = dictInfo.GetValue(valueObject, null);
//Convert it to a list to provide easy access to the item of interest. The List<> will be a set of key-value pairs.
List<object> values = ((IEnumerable)valueObject).Cast<object>().ToList();
//Use "GetValue" with the "value" parameter and the index to get the list object we want.
valueObject = values[index].GetType().GetProperty("Value").GetValue(values[index], null);
}
}
else
{
PropertyInfo propInfo = valueObject.GetType().GetProperty(prop);
if (propInfo != null)
{
valueObject = propInfo.GetValue(valueObject, null);
}
}
}
return valueObject;
}