score:1

Accepted answer

Daniel,

I found this article that has a solution that might work for you. http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/

So you would create the extension method...

  public static ExpandoObject ToExpando(this IDictionary<string, object> dictionary)
        {
            var expando = new ExpandoObject();
            var expandoDic = (IDictionary<string, object>)expando;

            // go through the items in the dictionary and copy over the key value pairs)
            foreach (var kvp in dictionary)
            {
                // if the value can also be turned into an ExpandoObject, then do it!
                if (kvp.Value is IDictionary<string, object>)
                {
                    var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
                    expandoDic.Add(kvp.Key, expandoValue);
                }
                else if (kvp.Value is ICollection)
                {
                    // iterate through the collection and convert any strin-object dictionaries
                    // along the way into expando objects
                    var itemList = new List<object>();
                    foreach (var item in (ICollection)kvp.Value)
                    {
                        if (item is IDictionary<string, object>)
                        {
                            var expandoItem = ((IDictionary<string, object>)item).ToExpando();
                            itemList.Add(expandoItem);
                        }
                        else
                        {
                            itemList.Add(item);
                        }
                    }

                    expandoDic.Add(kvp.Key, itemList);
                }
                else
                {
                    expandoDic.Add(kvp);
                }
            }

            return expando;
        }

Then from your Main function...

List<ExpandoObject> flattenSummary3 = new List<ExpandoObject>();
foreach ( var s in a.Summaries)
{
    flattenSummary3.Add(s.ToExpando());
}

And now the flattenSummary3 variable will contain a List of ExpandObjects that you can refer by properties.

I hope this helps.

score:1

While I accepted Ed's answer as it was very close, I'm providing the following code in case anyone else finds it useful. The key changes were to ensure that all uses of ExpandoObject were set as dynamic so that the final List was dynamic. Without these changes, examining the types inside the list still returned ExpandoObject (json serializing, for example, gave ExpandoObject instead of the expected property names/values).

First, the ToExpando() method (which should probably be called ToDynamic):

public static dynamic ToExpando(this IDictionary<string, object> dictionary)
{
    dynamic expando = new ExpandoObject();
    var expandoDic = (IDictionary<string, object>)expando;

    // go through the items in the dictionary and copy over the key value pairs)
    foreach (var kvp in dictionary)
    {
        // if the value can also be turned into an ExpandoObject, then do it!
        if (kvp.Value is IDictionary<string, object>)
        {
            var expandoValue = ((IDictionary<string, object>)kvp.Value).ToExpando();
            expandoDic.Add(kvp.Key, expandoValue);
        }
        else if (kvp.Value is ICollection)
        {
            // iterate through the collection and convert any strin-object dictionaries
            // along the way into expando objects
            var itemList = new List<object>();
            foreach (var item in (ICollection)kvp.Value)
            {
                if (item is IDictionary<string, object>)
                {
                    var expandoItem = ((IDictionary<string, object>)item).ToExpando();
                    itemList.Add(expandoItem);
                }
                else
                {
                    itemList.Add(item);
                }
            }

            expandoDic.Add(kvp.Key, itemList);
        }
        else
        {
            expandoDic.Add(kvp);
        }
    }

    return expando;
}

And the calling code would look like this:

    List<dynamic> summaries = new List<dynamic>();
    foreach (var s in a.Summaries)
    {
        summaries.Add(s.DynamicFields.ToExpando());
    }

Or the even more compact version:

    a.Summaries.Select(s => s.DynamicFields.ToExpando())

All of the above provide an object that could be referenced as:

    int year = a.Summaries[0].Year; // Year is a dynamic property of type int
    decimal income = a.Summaries[0].Income; // Income is a dynamic property of type decimal

Of course, the idea is I won't know the properties - but they can be serialized to json or, with some tweaking, be used to bind a grid or other UI element for display purposes.


Related Articles