views:

350

answers:

2

I need to get a dictionary of properties and their values from an object declared with the dynamic keyword in .NET 4? It seems using reflection for this will not work.

Example:

dynamic s = new ExpandoObject();
s.Path = "/Home";
s.Name = "Home";

// How do I enumerate the Path and Name properties and get their values?
IDictionary<string, object> propertyValues = ???
+6  A: 

In the case of ExpandoObject, the ExpandoObject class actually implements IDictionary<string, object> for its properties, so the solution is as trivial as casting:

IDictionary<string, object> propertyValues = (IDictionary<string, object>)s;

Note that this will not work for general dynamic objects. In these cases you will need to drop down to the DLR via IDynamicMetaObjectProvider.

itowlson
Thanks for that, unfortunately the sample was a little oversimplified. I need to be able to inspect a dynamic object without knowing what it's real type is.
Flatliner DOA
+3  A: 

There are several scenarios to consider. First of all, you need to check the type of your object. You can simply call GetType() for this. If the type does not implement IDynamicMetaObjectProvider, then you can use reflection same as for any other object. Something like:

var propertyInfo = test.GetType().GetProperties();

However, for IDynamicMetaObjectProvider implementations, the simple reflection doesn't work. Basically, you need to know more about this object. If it is ExpandoObject (which is one of the IDynamicMetaObjectProvider implementations), you can use the answer provided by itowlson. ExpandoObject stores its properties in a dictionary and you can simply cast your dynamic object to a dictionary.

If it's DynamicObject (another IDynamicMetaObjectProvider implementation), then you need to use whatever methods this DynamicObject exposes. DynamicObject isn't required to actually "store" its list of properties anywhere. For example, it might do something like this (I'm reusing an example from my blog post here: http://blogs.msdn.com/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject.aspx):

public class SampleObject : DynamicObject
{
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = binder.Name;
        return true;
    }
}

In this case, whenever you try to access a property (with any given name), the object simply returns the name of the property as a string.

dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".

So, you doesn't have anything to reflect over - this object doesn't have any properties, and at the same time all valid property names will work.

I'd say for IDynamicMetaObjectProvider implementations, you need to filter on known implementations where you can get a list of properties, such as ExpandoObject, and ignore (or throw an exception) for the rest.

Alexandra Rusina
It just seems to me that if the type I consume is Dynamic then I shouldn't be making assumptions about it's underlying type. I should be able to call GetDynamicMemberNames to get the list of members. It seems stupid that static types have better runtime inspection support than dynamic ones!
Flatliner DOA
You can override the GetDynamicMemberNames() method for a dynamic object to return the list names of dynamic members. The problem is that it's not guaranteed that every dynamic object has this method (ExpandoObject doesn't). It's not surprising that reflection works better for static types. It was created for them in the first place. With dynamics, you have to rely more on unit-testing and TDD.
Alexandra Rusina