Skip to main content
3 of 7
added 455 characters in body
Joelius
  • 355
  • 2
  • 12

Recursive conversion from ExpandoObject to Dictionary<string, object>

For my blazor library which is a modification of this awesome library I have to convert an ExpandoObject into a Dictionary<string, object> since ExpandoObjects aren't serialized properly in the newest preview versions of dotnet-core. See my question related to this for more details.

My current approach goes as follows:

private static Dictionary<string, object> ConvertDynamicToDictonary(IDictionary<string, object> value)
{
    return value.ToDictionary(
        p => p.Key,
        p =>
        {
            // if it's another IDict (might be a ExpandoObject or could also be an actual Dict containing ExpandoObjects) just go through it recursively
            if (p.Value is IDictionary<string, object> dict)
            {
                return ConvertDynamicToDictonary(dict);
            }

            // if it's an IEnumerable, it might have ExpandoObjects inside, so check for that
            if (p.Value is IEnumerable<object> list)
            {
                if (list.Any(o => o is ExpandoObject))
                {
                    // if it does contain ExpandoObjects, take all of those and also go through them recursively
                    return list
                        .Where(o => o is ExpandoObject)
                        .Select(o => ConvertDynamicToDictonary((ExpandoObject)o));
                }
            }

            // neither an IDict nor an IEnumerable -> it's probably fine to just return the value it has
            return p.Value;
        } 
    );
}

This works fine but I'm not sure about the IEnumerable part. If I omit the list.Any check it still works fine. New version (only write the IEnumerable part changed):

// if it's an IEnumerable, it might have ExpandoObjects inside, so check for that
if (p.Value is IEnumerable<object> list)
{
    // take all ExpandoObjects and go through them recursively
    return list
        .Where(o => o is ExpandoObject)
        .Select(o => ConvertDynamicToDictonary((ExpandoObject)o));
}

I have also tried using IEnumerable<ExpandoObject> instead of just IEnumerable<object> to see if that would work and maybe be cleaner and I can confirm that that does not work (throws error).

What I would like to know now is, if it's a good idea to omit the Any check and which option is more performant (and why) and/or cleaner.
Also please mention every small thing that bugs you, I always want to make it as perfect as possible :)

I first wanted to post this on StackOverflow but I think it fits better on here - correct me if I'm wrong.

EDIT 0:
This function is only called from inside the library and already marked private static. I simply forgot to put that the first time, this is now corrected.
This answer suggests changing it into a extension method. Would this still be the "correct" way of doing it, now that it's clear that the method is not supposed to be called outside of the library itself?

Joelius
  • 355
  • 2
  • 12