RealWorldCoder
RealWorldCoder

Reputation: 1021

Not able to get dynamic properties with reflection

A dynamic object is generated using a Json deserializing component (Jil) I am using, and I am able to access the properties directly. But I don't know their names in advance, so I am trying to get the names with reflection. I tried doing this:

var props = myDynObj.GetType().GetProperties();

but the page times out. Doesn't give me anything in debugger, just sits there doing nothing, or something and not telling me.

This even happens when I even do this:

var t = myDynObj.GetType();

But when I do this, it works:

var val = myDynObj.MyStaticValue1

Just can't really do anything else with it. Anyonw know why, and how I can get this to work?

Upvotes: 1

Views: 674

Answers (1)

caesay
caesay

Reputation: 17213

Please allow me to note:

Before I get started, if you don't know the members already when you're parsing JSON, you should not be parsing into a dynamic object. The built-in .Net JavaScriptConverter class can parse JSON into a IDictionary<string, object> which would be much better for you.

However, if you still want to use dynamic objects for some reason:

If you want to stick with your current library: I dont know how exactly that class is working, and I'm not saying this is the best solution, but by looking at the source it jumps out to me that you can grab a list of the ObjectMembers keys using reflection.

Type t = typeof(JsonObject)
var fi = t.GetField("ObjectMembers", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
IEnumerable<string> keys = ((Dictionary<string, JsonObject>)fi.GetValue(obj)).Keys;


Edit: Seeing that JsonObject implements IDynamicMetaObjectProvider, the following method mentioned in this question will also work on it:

public static IEnumerable<string> GetMemberNames(object target, bool dynamicOnly = false)
{
    var tList = new List<string>();
    if (!dynamicOnly)
    {
       tList.AddRange(target.GetType().GetProperties().Select(it => it.Name));
    }

    var tTarget = target as IDynamicMetaObjectProvider;
    if (tTarget !=null)
    {
        tList.AddRange(tTarget.GetMetaObject(Expression.Constant(tTarget)).GetDynamicMemberNames());
    }else
    {

        if (ComObjectType != null && ComObjectType.IsInstanceOfType(target) && ComBinder.IsAvailable)
        {
            tList.AddRange(ComBinder.GetDynamicDataMemberNames(target));
        }
    }
    return tList;
} 



If you are open to trying a different JSON converter: try this class here: http://pastie.org/private/vhwfvz0pg06zmjqirtlxa I'm not sure where I found it (I can't take credit) but here is an example of how to use it how you want:

// Create dynamic object from JSON string
dynamic obj = DynamicJsonConverter.CreateSerializer().Deserialize("JSON STRING", typeof(object));
// Get json value
string str = obj.someValue;
// Get list of members
IEnumerable<string> members = (IDictionary<string, object>)obj).Keys

Personally I like using the second one, it is simple and easy to use - and builds off of the built in .Net JSON parser.

Upvotes: 1

Related Questions