Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a Dictionary Value Using Reflection

I am trying to access an object stored in a dictionary of type String, UnknownClass. I have the key, and know the value is one of several container classes. Since the value is passed to a method that takes an object, I do not need to know the type of the class stored as a value. I also need to call ContainsKey to confirm the key exists.

I have tried the following methods with no success:

Dictionary<String, object> list = (Dictionary<String, object>)source.GetType().GetProperty(dictionaryName).GetValue(source, null);
nextSource = list[key];

Which gives me a casting error, and:

nextSource = source.GetType().GetMethod("get_Item").Invoke(source, new object[] { key });

Which gives me a null reference exception.

Here is a bit more of the code, although I am not quite sure it will help much.

private void SetValue(object source, String path, String value)
{
    if (path.Contains('.'))
    {
        //  If this is not the ending Property, continue recursing
        int index = path.IndexOf('.');
        String property = path.Substring(0, index);

        object nextSource;
        if(property.Contains("*"))
        {
            path = path.Substring(index + 1);
            index = path.IndexOf('.');
            String dictionaryName = path.Substring(0, index);

            Dictionary<String, object> list = (Dictionary<String, object>)source.GetType().GetProperty(dictionaryName).GetValue(source, null);
            nextSource = list[property.Substring(1)];
            //property = property.Substring(1);
            //nextSource = source.GetType().GetMethod("Item").Invoke(source, new[] { property });
        } ...

The dictionary being accessed is defined in the PersonObject class as such:

public class PersonObject
{
    public String Name { get; set; }
    public AddressObject Address { get; set; }
    public Dictionary<String, HobbyObject> Hobbies { get; set; }

The value of Path, at this stage, is set to "*Hiking.Hobbies.Hobby". Basically, the path string allows me to navigate to a Property in a subclass, and I need the Dictionary to access properties for a list of the same class.

like image 911
Tim Avatar asked Jul 12 '13 21:07

Tim


2 Answers

The Dictionary<TKey, TValue> Class implements the non-generic IDictionary Interface. So if you have a variable of tye object containing the reference to a Dictionary<String, HobbyObject> instance, you can retrieve values in the dictionary as follows:

object obj = new Dictionary<String, HobbyObject>
{
    { "Hobby", new HobbyObject() }
};

IDictionary dict = obj as IDictionary;
if (dict != null)
{
    object value = dict["Hobby"];
    // value is a HobbyObject
}
like image 90
dtb Avatar answered Oct 10 '22 02:10

dtb


It sounds like you're trying to do this:

var source = new Dictionary<string, object>();
var key = "some key";
source.Add(key, "some value");

var property = source.GetType().GetProperty("Item");
var value = property.GetValue(source, new[] { key });

Console.WriteLine(value.ToString()); // some value

Update: The problem is that a Dictionary<string, HobbyObject> cannot be cast to a Dictionary<string, object>. I think you'd have to do this:

private void SetValue(object source, String path, String value)
{
    if (path.Contains('.'))
    {
        //  If this is not the ending Property, continue recursing
        int index = path.IndexOf('.');
        String property = path.Substring(0, index);

        object nextSource;
        if(property[0] = '*')
        {
            path = path.Substring(index + 1);
            index = path.IndexOf('.');
            String dictionaryName = path.Substring(0, index);

            property = property.Substring(1);

            Object list = source.GetType().GetProperty(dictionaryName)
                                .GetValue(source, null);
            nextSource = list.GetType().GetProperty("Item")
                             .GetValue(list, new[] { property });
        }
like image 37
p.s.w.g Avatar answered Oct 10 '22 02:10

p.s.w.g