Is it possible to query list of ExpandoObject?

Stan picture Stan · Sep 11, 2013 · Viewed 12k times · Source

I wonder if it is possible to query ExpandoObject with regular LINQ? Reason is that I have dynamic ExpandoObject but I need to do some querying before I can pass further.

It has some properties that always stay e.g. Id, Notes but also some dynamic properties that I cannot control.

Here is how my list of them looks like

[
  {
    "Id": 1,
    "FileId": 1,
    "Notes": "",
    "1": "12.02.1991"
  },
  {
    "Id": 2,
    "FileId": 2,
    "Notes": "",
    "1": "12.02.1991"
  }
]

Code

As you can see I have my static items and then I make sure that every item dynamic keys become that item properties. In this example 1 is key and 12.02.1991 is value

var generatedItems = new List<object>();

foreach (var item in items)
{
    var modifiedItem = new List<KeyValuePair<string, object>>
    {
        new KeyValuePair<string, object>("Id", item.Id),
        new KeyValuePair<string, object>("FileId", item.FileId),
        new KeyValuePair<string, object>("Notes", item.Notes)
    };
    modifiedItem.AddRange(item.Fields.Select(field => new KeyValuePair<string, object>(field.Key, field.Value)));

    generatedItems.Add(ConvertToExpandoObjects(modifiedItem)); // Here I construct object from key/value pairs
}

return generatedItems; // Is it possible to query this thing?

I don't think this is relevant but here is my ConvertToExpandoObjects funciton.

public static dynamic ConvertToExpandoObjects(IEnumerable<KeyValuePair<string, object>> pairs)
{
    IDictionary<string, object> result = new ExpandoObject();
    foreach (var pair in pairs)
        result.Add(pair.Key, pair.Value);
    return result;
}

I tried to simply do something like generatedItems.Where(x => x.); but obviously it gives me nothing to work on since it doesn't know that these objects have Id etc..

So is it possible to query it and if so, then how?

Answer

dcastro picture dcastro · Sep 11, 2013

Your suggestion is right, you would be able to query a collection of dynamic objects using the dot notation.

var ids = generatedItems.Cast<dynamic>().Select(x => x.Id);

However, keep in mind that there's no type safety here and, as you stated, IntelliSense is of no use, since you're using dynamic objects.

If your code depends on whether one of those objects have an optional property (e.g., some have "Title", others don't), then it will require a little more manual labor.

if((generatedItems as IDictionary<String, object>).ContainsKey("Title")) {

}