Recursive conversion from ExpandoObject to DictionaryDictionary of attributes and valuesCompare dicts and record changesMatch two dictionary keys efficiently in PythonGet all combination of a nested object with arbitrary levelsWriting an anagram efficientlyList all possible permutations from a python dictionary of listshow to filter text from a string and convert it to dictionary and check for matching values in pythonRecursive object/array filter by keyRecursive parser from Binary to JSON outputBuilding nested dictionaries to dump it to .json later

What happens if the limit of 4 billion files was exceeded in an ext4 partition?

How frequently do Russian people still refer to others by their patronymic (отчество)?

How to deal with a Murder Hobo Paladin?

How can solar sailed ships be protected from space debris?

How to improve the size of cells in this table?

Does Evolution Sage proliferate Blast Zone when played?

Is there a typical layout to blocking installed for backing in new construction framing?

Show that there are infinitely more problems than we will ever be able to compute

What is the fundamental difference between catching whales and hunting other animals?

What does it mean for a bass player to play "on the one"?

Creating patterns

Implementing absolute value function in c

Can a wizard delay learning new spells from leveling up, and instead learn different spells later?

Do I need to be legally qualified to install a Hive smart thermostat?

How can one synthesise a conjugated alkyne chain?

Contributing to a candidate as a Foreign National US Resident?

How to respond to someone who condemns behavior similar to what they exhibit?

What/Where usage English vs Japanese

Why did moving the mouse cursor cause Windows 95 to run more quickly?

Can a Time Lord survive with just one heart?

Could you sell yourself into slavery in the USA?

Advice for making/keeping shredded chicken moist?

Has chattel slavery ever been used as a criminal punishment in the USA since the passage of the Thirteenth Amendment?

What is this arch-and-tower near a road?



Recursive conversion from ExpandoObject to Dictionary


Dictionary of attributes and valuesCompare dicts and record changesMatch two dictionary keys efficiently in PythonGet all combination of a nested object with arbitrary levelsWriting an anagram efficientlyList all possible permutations from a python dictionary of listshow to filter text from a string and convert it to dictionary and check for matching values in pythonRecursive object/array filter by keyRecursive parser from Binary to JSON outputBuilding nested dictionaries to dump it to .json later






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








2












$begingroup$


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:



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 1:



Because I feel like I have not made clear how I will use this function, I have some demo-code for you. This will of course not compile, it's just to show how and why I need this method.

If this edit is problematic because I'm adding new code, I will post a new, more complete question later on (I sadly don't have anymore time today).



// this class (like all the others) are of course much more complicated than this. 
// There's also a lot of abstraction etc (you can see the actual code on the github I've linked at the start).
SomeConfig config = new SomeConfig

Options = new SomeOptions

SomeInt = 2,
SomeString = null, // any trace of this property will not be present in the expando object
Axes = new List<Axis>

new Axis() // this axis will also be an expandoObject after being extracted from the json

,
Data = new SomeData

Data = new List<int> 1, 2, 3, 4, 5 ,
SomeString = "asdf"

;

dynamic expando = /* ParseConfigToJsonWithoutNulls -> ParseJsonToExpandoObject */
IJSRuntime jsRT = GetTheRuntime();
jsRT.InvokeAsync("blabla", expando); // this would NOT work because ExpandoObject cannot be serialized to json correctly and throws a runtime error


// this method is what we need in the best way possible without missing something :)
Dictionary<string, object> dictFromExpando = ConvertExpandoToDictonary(expando);

// so the only purpose of the ConvertExpandoToDictonary is to recursively convert all the ExpandoObjects to Dictionaries as they are serializable
// I have to do this recursively since there are nested ExpandoObjects that were created when parsing the huge json to the ExpandoObject with Json.Net
// I have decided to go with Dictionaries because it works and ExpandoObject implements the interface IDictionary<string, object>
jsRT.InvokeAsync("blabla", dictFromExpando); // this now works perfectly fine
```









share|improve this question









New contributor



Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$







  • 2




    $begingroup$
    Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 3 → 2
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    7 hours ago










  • $begingroup$
    @SᴀᴍOnᴇᴌᴀ Sorry I did not know. I feel like this was just a small mistake I made which may have caused some misunderstandings. Do I really have to ask a new question just for that (becaues I feel like my main concern didn't have to do with that at all) or how would you recommend me clearing that misunderstanding up to the concerned question?
    $endgroup$
    – Joelius
    7 hours ago






  • 2




    $begingroup$
    I would await sufficient answers and comments. Then you could self-answer or accept if you please, and perhaps also ask a follow-up question.
    $endgroup$
    – dfhwze
    7 hours ago






  • 1




    $begingroup$
    The rollback is being discussed on meta.
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    6 hours ago

















2












$begingroup$


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:



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 1:



Because I feel like I have not made clear how I will use this function, I have some demo-code for you. This will of course not compile, it's just to show how and why I need this method.

If this edit is problematic because I'm adding new code, I will post a new, more complete question later on (I sadly don't have anymore time today).



// this class (like all the others) are of course much more complicated than this. 
// There's also a lot of abstraction etc (you can see the actual code on the github I've linked at the start).
SomeConfig config = new SomeConfig

Options = new SomeOptions

SomeInt = 2,
SomeString = null, // any trace of this property will not be present in the expando object
Axes = new List<Axis>

new Axis() // this axis will also be an expandoObject after being extracted from the json

,
Data = new SomeData

Data = new List<int> 1, 2, 3, 4, 5 ,
SomeString = "asdf"

;

dynamic expando = /* ParseConfigToJsonWithoutNulls -> ParseJsonToExpandoObject */
IJSRuntime jsRT = GetTheRuntime();
jsRT.InvokeAsync("blabla", expando); // this would NOT work because ExpandoObject cannot be serialized to json correctly and throws a runtime error


// this method is what we need in the best way possible without missing something :)
Dictionary<string, object> dictFromExpando = ConvertExpandoToDictonary(expando);

// so the only purpose of the ConvertExpandoToDictonary is to recursively convert all the ExpandoObjects to Dictionaries as they are serializable
// I have to do this recursively since there are nested ExpandoObjects that were created when parsing the huge json to the ExpandoObject with Json.Net
// I have decided to go with Dictionaries because it works and ExpandoObject implements the interface IDictionary<string, object>
jsRT.InvokeAsync("blabla", dictFromExpando); // this now works perfectly fine
```









share|improve this question









New contributor



Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$







  • 2




    $begingroup$
    Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 3 → 2
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    7 hours ago










  • $begingroup$
    @SᴀᴍOnᴇᴌᴀ Sorry I did not know. I feel like this was just a small mistake I made which may have caused some misunderstandings. Do I really have to ask a new question just for that (becaues I feel like my main concern didn't have to do with that at all) or how would you recommend me clearing that misunderstanding up to the concerned question?
    $endgroup$
    – Joelius
    7 hours ago






  • 2




    $begingroup$
    I would await sufficient answers and comments. Then you could self-answer or accept if you please, and perhaps also ask a follow-up question.
    $endgroup$
    – dfhwze
    7 hours ago






  • 1




    $begingroup$
    The rollback is being discussed on meta.
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    6 hours ago













2












2








2





$begingroup$


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:



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 1:



Because I feel like I have not made clear how I will use this function, I have some demo-code for you. This will of course not compile, it's just to show how and why I need this method.

If this edit is problematic because I'm adding new code, I will post a new, more complete question later on (I sadly don't have anymore time today).



// this class (like all the others) are of course much more complicated than this. 
// There's also a lot of abstraction etc (you can see the actual code on the github I've linked at the start).
SomeConfig config = new SomeConfig

Options = new SomeOptions

SomeInt = 2,
SomeString = null, // any trace of this property will not be present in the expando object
Axes = new List<Axis>

new Axis() // this axis will also be an expandoObject after being extracted from the json

,
Data = new SomeData

Data = new List<int> 1, 2, 3, 4, 5 ,
SomeString = "asdf"

;

dynamic expando = /* ParseConfigToJsonWithoutNulls -> ParseJsonToExpandoObject */
IJSRuntime jsRT = GetTheRuntime();
jsRT.InvokeAsync("blabla", expando); // this would NOT work because ExpandoObject cannot be serialized to json correctly and throws a runtime error


// this method is what we need in the best way possible without missing something :)
Dictionary<string, object> dictFromExpando = ConvertExpandoToDictonary(expando);

// so the only purpose of the ConvertExpandoToDictonary is to recursively convert all the ExpandoObjects to Dictionaries as they are serializable
// I have to do this recursively since there are nested ExpandoObjects that were created when parsing the huge json to the ExpandoObject with Json.Net
// I have decided to go with Dictionaries because it works and ExpandoObject implements the interface IDictionary<string, object>
jsRT.InvokeAsync("blabla", dictFromExpando); // this now works perfectly fine
```









share|improve this question









New contributor



Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$




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:



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 1:



Because I feel like I have not made clear how I will use this function, I have some demo-code for you. This will of course not compile, it's just to show how and why I need this method.

If this edit is problematic because I'm adding new code, I will post a new, more complete question later on (I sadly don't have anymore time today).



// this class (like all the others) are of course much more complicated than this. 
// There's also a lot of abstraction etc (you can see the actual code on the github I've linked at the start).
SomeConfig config = new SomeConfig

Options = new SomeOptions

SomeInt = 2,
SomeString = null, // any trace of this property will not be present in the expando object
Axes = new List<Axis>

new Axis() // this axis will also be an expandoObject after being extracted from the json

,
Data = new SomeData

Data = new List<int> 1, 2, 3, 4, 5 ,
SomeString = "asdf"

;

dynamic expando = /* ParseConfigToJsonWithoutNulls -> ParseJsonToExpandoObject */
IJSRuntime jsRT = GetTheRuntime();
jsRT.InvokeAsync("blabla", expando); // this would NOT work because ExpandoObject cannot be serialized to json correctly and throws a runtime error


// this method is what we need in the best way possible without missing something :)
Dictionary<string, object> dictFromExpando = ConvertExpandoToDictonary(expando);

// so the only purpose of the ConvertExpandoToDictonary is to recursively convert all the ExpandoObjects to Dictionaries as they are serializable
// I have to do this recursively since there are nested ExpandoObjects that were created when parsing the huge json to the ExpandoObject with Json.Net
// I have decided to go with Dictionaries because it works and ExpandoObject implements the interface IDictionary<string, object>
jsRT.InvokeAsync("blabla", dictFromExpando); // this now works perfectly fine
```






c# recursion dictionary






share|improve this question









New contributor



Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










share|improve this question









New contributor



Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








share|improve this question




share|improve this question








edited 6 hours ago







Joelius













New contributor



Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.








asked 8 hours ago









JoeliusJoelius

1112 bronze badges




1112 bronze badges




New contributor



Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




New contributor




Joelius is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









  • 2




    $begingroup$
    Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 3 → 2
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    7 hours ago










  • $begingroup$
    @SᴀᴍOnᴇᴌᴀ Sorry I did not know. I feel like this was just a small mistake I made which may have caused some misunderstandings. Do I really have to ask a new question just for that (becaues I feel like my main concern didn't have to do with that at all) or how would you recommend me clearing that misunderstanding up to the concerned question?
    $endgroup$
    – Joelius
    7 hours ago






  • 2




    $begingroup$
    I would await sufficient answers and comments. Then you could self-answer or accept if you please, and perhaps also ask a follow-up question.
    $endgroup$
    – dfhwze
    7 hours ago






  • 1




    $begingroup$
    The rollback is being discussed on meta.
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    6 hours ago












  • 2




    $begingroup$
    Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 3 → 2
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    7 hours ago










  • $begingroup$
    @SᴀᴍOnᴇᴌᴀ Sorry I did not know. I feel like this was just a small mistake I made which may have caused some misunderstandings. Do I really have to ask a new question just for that (becaues I feel like my main concern didn't have to do with that at all) or how would you recommend me clearing that misunderstanding up to the concerned question?
    $endgroup$
    – Joelius
    7 hours ago






  • 2




    $begingroup$
    I would await sufficient answers and comments. Then you could self-answer or accept if you please, and perhaps also ask a follow-up question.
    $endgroup$
    – dfhwze
    7 hours ago






  • 1




    $begingroup$
    The rollback is being discussed on meta.
    $endgroup$
    – Sᴀᴍ Onᴇᴌᴀ
    6 hours ago







2




2




$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 3 → 2
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
7 hours ago




$begingroup$
Welcome to Code Review! Please see What to do when someone answers. I have rolled back Rev 3 → 2
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
7 hours ago












$begingroup$
@SᴀᴍOnᴇᴌᴀ Sorry I did not know. I feel like this was just a small mistake I made which may have caused some misunderstandings. Do I really have to ask a new question just for that (becaues I feel like my main concern didn't have to do with that at all) or how would you recommend me clearing that misunderstanding up to the concerned question?
$endgroup$
– Joelius
7 hours ago




$begingroup$
@SᴀᴍOnᴇᴌᴀ Sorry I did not know. I feel like this was just a small mistake I made which may have caused some misunderstandings. Do I really have to ask a new question just for that (becaues I feel like my main concern didn't have to do with that at all) or how would you recommend me clearing that misunderstanding up to the concerned question?
$endgroup$
– Joelius
7 hours ago




2




2




$begingroup$
I would await sufficient answers and comments. Then you could self-answer or accept if you please, and perhaps also ask a follow-up question.
$endgroup$
– dfhwze
7 hours ago




$begingroup$
I would await sufficient answers and comments. Then you could self-answer or accept if you please, and perhaps also ask a follow-up question.
$endgroup$
– dfhwze
7 hours ago




1




1




$begingroup$
The rollback is being discussed on meta.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
6 hours ago




$begingroup$
The rollback is being discussed on meta.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
6 hours ago










3 Answers
3






active

oldest

votes


















2












$begingroup$

Your method is meant to handle ExpandoObjects explicitly, so it would be better named ConvertExpandoObjectToDictonary, and would probably be less confusing if it actually took an ExpandoObject as the parameter:



Dictionary<string, object> ConvertExpandoObjectToDictonary(ExpandoObject expandoObject);


This is what the public API should look like; you can keep the current method as it is (since you need to call it recursively) but make it private and hide it behind the clearer public API.




This doesn't really make sense:



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));



You are looking for a single ExpandoObject, and then assuming everything you might need is an expando object and ignoring everything else. I think you want something like this instead, which keeps non-expando entries:



return list
.Select(o => o is ExpandoObject
? ConvertDynamicToDictonary((ExpandoObject)o)
: o
);





share|improve this answer









$endgroup$












  • $begingroup$
    You are enforcing a signature and flow based on a strict interpretation of the spec. Since the spec is lacking some context, I find this approach OK.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze sorry; I'm not sure what you mean? (I'm mostly going by the title, which suggests the purpose of this method is exactly to process ExpandoObjects)
    $endgroup$
    – VisualMelon
    7 hours ago










  • $begingroup$
    The OP uses a dict both to process dictionaries and expando's. You took the ambiguity away. This has an impact on the algorithm, if there really are dictionaries to be processed that aren't expando's. The OP should perhaps make clear the usage of dict.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze I think I see what you mean. I'd maintain that if the intention is to convert ExpandoObjects (which is how I read the OP) then the API should reflect that; the work can be referred to a method that processes dictionaries (per the OP): it needn't have any influence on the algorithm.
    $endgroup$
    – VisualMelon
    7 hours ago







  • 1




    $begingroup$
    yes :) that would be OK. Let's stop hijacking the comments of this answer now :p
    $endgroup$
    – dfhwze
    7 hours ago



















1












$begingroup$

Inconsistent definition of ExpandoObject. It's IDictionary<string, object> here:




if (p.Value is IDictionary<string, object> dict)

return ConvertDynamicToDictonary(dict); // <- possibly already visited?




and ExpandoObject here:




if (list.Any(o => o is ExpandoObject))

// ..




I would opt to use IDictionary<string, object> both to improve consistency and flexibility of handling instances in the hierarchy.




It is not clear whether the structure of the hierarchical data is a tree or a cyclic graph. This has impact on a possible infinite recursion. In case of a cyclic graph, I would keep track of visited references.




Not all sequences are generic classes.



This condition..




if (p.Value is IEnumerable<object> list)




..does not cover when p.Value is IEnumerable but not IEnumerable<object>. As note in another answer, be careful with false positives (like string).




What if value is null? Try avoiding null reference exceptions in your code.








share|improve this answer











$endgroup$












  • $begingroup$
    Thanks for the ideas. The ExpandoObject should always be a tree since it is just an instance of a class with all traces of null properties removed. This is necessary for correctly invoking some Javascript.
    $endgroup$
    – Joelius
    7 hours ago


















0












$begingroup$

A few minor stylistic bits that may increase its utility:



  • since you take in an IDictionary, return an IDictionary.

  • make it static as it accesses no instance data or methods.

  • since it's now static, make it an extension method.

  • validate the parameter passed in.

Also:



  • since it's a single return statement, make it an expression body.

Further:



  • yeah, the .Any() is redundant (and less performant if there is an ExpandoObject in the collection) with the .Where() criteria, so no need for it.

  • allowed for non-generic IEnumerable.

  • renamed some of the locals to be clearer as to their meaning.

Giving:



static IDictionary<string, object> ConvertDynamicToDictionary(this IDictionary<string, object> source) => source?.ToDictionary(
keySelector => keySelector.Key,
elementSelector =>

object value = elementSelector.Value;

// if it's another IDict (might be a ExpandoObject or could also be an actual Dict containing ExpandoObjects) just go through it recursively
if (value is IDictionary<string, object> dictionary)

return dictionary.ConvertDynamicToDictionary();


// A special case since string implements IEnumerable.
if (value is string stringValue)

return stringValue;


// if it's an IEnumerable, it might have ExpandoObjects inside, so check for that
if (value is IEnumerable enumerable)

// if it does contain ExpandoObjects, take all of those and also go through them recursively
return enumerable
.Cast<object>()
.Select(element => element is IDictionary<string, object> expando
? expando.ConvertDynamicToDictionary()
: element);


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





share|improve this answer











$endgroup$












  • $begingroup$
    Ugh, string implements IEnumerable.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    Clear points, thank you. Yes I already wanted to point out that IEnumerable is used seemingly everywhere and ask if that would cause issues (it would just decrease the performance right?). Also I have edited my question regarding the signature because the method is already private and static I just forgot to write that.
    $endgroup$
    – Joelius
    7 hours ago











  • $begingroup$
    It's not that IEnumerable decreases performance, it's that the .Any() followed by .Where() with the same lambda does the same checking, and therefore .Any() is redundant.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    I see. My edit has now been rolled back because I edited the code which you're not supposed to do. My method is actually private static - would you still recommend me converting it into an extension method?
    $endgroup$
    – Joelius
    7 hours ago










  • $begingroup$
    I mean, I like them. Especially when the parameter is an interface.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago













Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);






Joelius is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f223375%2frecursive-conversion-from-expandoobject-to-dictionarystring-object%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









2












$begingroup$

Your method is meant to handle ExpandoObjects explicitly, so it would be better named ConvertExpandoObjectToDictonary, and would probably be less confusing if it actually took an ExpandoObject as the parameter:



Dictionary<string, object> ConvertExpandoObjectToDictonary(ExpandoObject expandoObject);


This is what the public API should look like; you can keep the current method as it is (since you need to call it recursively) but make it private and hide it behind the clearer public API.




This doesn't really make sense:



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));



You are looking for a single ExpandoObject, and then assuming everything you might need is an expando object and ignoring everything else. I think you want something like this instead, which keeps non-expando entries:



return list
.Select(o => o is ExpandoObject
? ConvertDynamicToDictonary((ExpandoObject)o)
: o
);





share|improve this answer









$endgroup$












  • $begingroup$
    You are enforcing a signature and flow based on a strict interpretation of the spec. Since the spec is lacking some context, I find this approach OK.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze sorry; I'm not sure what you mean? (I'm mostly going by the title, which suggests the purpose of this method is exactly to process ExpandoObjects)
    $endgroup$
    – VisualMelon
    7 hours ago










  • $begingroup$
    The OP uses a dict both to process dictionaries and expando's. You took the ambiguity away. This has an impact on the algorithm, if there really are dictionaries to be processed that aren't expando's. The OP should perhaps make clear the usage of dict.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze I think I see what you mean. I'd maintain that if the intention is to convert ExpandoObjects (which is how I read the OP) then the API should reflect that; the work can be referred to a method that processes dictionaries (per the OP): it needn't have any influence on the algorithm.
    $endgroup$
    – VisualMelon
    7 hours ago







  • 1




    $begingroup$
    yes :) that would be OK. Let's stop hijacking the comments of this answer now :p
    $endgroup$
    – dfhwze
    7 hours ago
















2












$begingroup$

Your method is meant to handle ExpandoObjects explicitly, so it would be better named ConvertExpandoObjectToDictonary, and would probably be less confusing if it actually took an ExpandoObject as the parameter:



Dictionary<string, object> ConvertExpandoObjectToDictonary(ExpandoObject expandoObject);


This is what the public API should look like; you can keep the current method as it is (since you need to call it recursively) but make it private and hide it behind the clearer public API.




This doesn't really make sense:



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));



You are looking for a single ExpandoObject, and then assuming everything you might need is an expando object and ignoring everything else. I think you want something like this instead, which keeps non-expando entries:



return list
.Select(o => o is ExpandoObject
? ConvertDynamicToDictonary((ExpandoObject)o)
: o
);





share|improve this answer









$endgroup$












  • $begingroup$
    You are enforcing a signature and flow based on a strict interpretation of the spec. Since the spec is lacking some context, I find this approach OK.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze sorry; I'm not sure what you mean? (I'm mostly going by the title, which suggests the purpose of this method is exactly to process ExpandoObjects)
    $endgroup$
    – VisualMelon
    7 hours ago










  • $begingroup$
    The OP uses a dict both to process dictionaries and expando's. You took the ambiguity away. This has an impact on the algorithm, if there really are dictionaries to be processed that aren't expando's. The OP should perhaps make clear the usage of dict.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze I think I see what you mean. I'd maintain that if the intention is to convert ExpandoObjects (which is how I read the OP) then the API should reflect that; the work can be referred to a method that processes dictionaries (per the OP): it needn't have any influence on the algorithm.
    $endgroup$
    – VisualMelon
    7 hours ago







  • 1




    $begingroup$
    yes :) that would be OK. Let's stop hijacking the comments of this answer now :p
    $endgroup$
    – dfhwze
    7 hours ago














2












2








2





$begingroup$

Your method is meant to handle ExpandoObjects explicitly, so it would be better named ConvertExpandoObjectToDictonary, and would probably be less confusing if it actually took an ExpandoObject as the parameter:



Dictionary<string, object> ConvertExpandoObjectToDictonary(ExpandoObject expandoObject);


This is what the public API should look like; you can keep the current method as it is (since you need to call it recursively) but make it private and hide it behind the clearer public API.




This doesn't really make sense:



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));



You are looking for a single ExpandoObject, and then assuming everything you might need is an expando object and ignoring everything else. I think you want something like this instead, which keeps non-expando entries:



return list
.Select(o => o is ExpandoObject
? ConvertDynamicToDictonary((ExpandoObject)o)
: o
);





share|improve this answer









$endgroup$



Your method is meant to handle ExpandoObjects explicitly, so it would be better named ConvertExpandoObjectToDictonary, and would probably be less confusing if it actually took an ExpandoObject as the parameter:



Dictionary<string, object> ConvertExpandoObjectToDictonary(ExpandoObject expandoObject);


This is what the public API should look like; you can keep the current method as it is (since you need to call it recursively) but make it private and hide it behind the clearer public API.




This doesn't really make sense:



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));



You are looking for a single ExpandoObject, and then assuming everything you might need is an expando object and ignoring everything else. I think you want something like this instead, which keeps non-expando entries:



return list
.Select(o => o is ExpandoObject
? ConvertDynamicToDictonary((ExpandoObject)o)
: o
);






share|improve this answer












share|improve this answer



share|improve this answer










answered 7 hours ago









VisualMelonVisualMelon

4,50612 silver badges29 bronze badges




4,50612 silver badges29 bronze badges











  • $begingroup$
    You are enforcing a signature and flow based on a strict interpretation of the spec. Since the spec is lacking some context, I find this approach OK.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze sorry; I'm not sure what you mean? (I'm mostly going by the title, which suggests the purpose of this method is exactly to process ExpandoObjects)
    $endgroup$
    – VisualMelon
    7 hours ago










  • $begingroup$
    The OP uses a dict both to process dictionaries and expando's. You took the ambiguity away. This has an impact on the algorithm, if there really are dictionaries to be processed that aren't expando's. The OP should perhaps make clear the usage of dict.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze I think I see what you mean. I'd maintain that if the intention is to convert ExpandoObjects (which is how I read the OP) then the API should reflect that; the work can be referred to a method that processes dictionaries (per the OP): it needn't have any influence on the algorithm.
    $endgroup$
    – VisualMelon
    7 hours ago







  • 1




    $begingroup$
    yes :) that would be OK. Let's stop hijacking the comments of this answer now :p
    $endgroup$
    – dfhwze
    7 hours ago

















  • $begingroup$
    You are enforcing a signature and flow based on a strict interpretation of the spec. Since the spec is lacking some context, I find this approach OK.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze sorry; I'm not sure what you mean? (I'm mostly going by the title, which suggests the purpose of this method is exactly to process ExpandoObjects)
    $endgroup$
    – VisualMelon
    7 hours ago










  • $begingroup$
    The OP uses a dict both to process dictionaries and expando's. You took the ambiguity away. This has an impact on the algorithm, if there really are dictionaries to be processed that aren't expando's. The OP should perhaps make clear the usage of dict.
    $endgroup$
    – dfhwze
    7 hours ago










  • $begingroup$
    @dfhwze I think I see what you mean. I'd maintain that if the intention is to convert ExpandoObjects (which is how I read the OP) then the API should reflect that; the work can be referred to a method that processes dictionaries (per the OP): it needn't have any influence on the algorithm.
    $endgroup$
    – VisualMelon
    7 hours ago







  • 1




    $begingroup$
    yes :) that would be OK. Let's stop hijacking the comments of this answer now :p
    $endgroup$
    – dfhwze
    7 hours ago
















$begingroup$
You are enforcing a signature and flow based on a strict interpretation of the spec. Since the spec is lacking some context, I find this approach OK.
$endgroup$
– dfhwze
7 hours ago




$begingroup$
You are enforcing a signature and flow based on a strict interpretation of the spec. Since the spec is lacking some context, I find this approach OK.
$endgroup$
– dfhwze
7 hours ago












$begingroup$
@dfhwze sorry; I'm not sure what you mean? (I'm mostly going by the title, which suggests the purpose of this method is exactly to process ExpandoObjects)
$endgroup$
– VisualMelon
7 hours ago




$begingroup$
@dfhwze sorry; I'm not sure what you mean? (I'm mostly going by the title, which suggests the purpose of this method is exactly to process ExpandoObjects)
$endgroup$
– VisualMelon
7 hours ago












$begingroup$
The OP uses a dict both to process dictionaries and expando's. You took the ambiguity away. This has an impact on the algorithm, if there really are dictionaries to be processed that aren't expando's. The OP should perhaps make clear the usage of dict.
$endgroup$
– dfhwze
7 hours ago




$begingroup$
The OP uses a dict both to process dictionaries and expando's. You took the ambiguity away. This has an impact on the algorithm, if there really are dictionaries to be processed that aren't expando's. The OP should perhaps make clear the usage of dict.
$endgroup$
– dfhwze
7 hours ago












$begingroup$
@dfhwze I think I see what you mean. I'd maintain that if the intention is to convert ExpandoObjects (which is how I read the OP) then the API should reflect that; the work can be referred to a method that processes dictionaries (per the OP): it needn't have any influence on the algorithm.
$endgroup$
– VisualMelon
7 hours ago





$begingroup$
@dfhwze I think I see what you mean. I'd maintain that if the intention is to convert ExpandoObjects (which is how I read the OP) then the API should reflect that; the work can be referred to a method that processes dictionaries (per the OP): it needn't have any influence on the algorithm.
$endgroup$
– VisualMelon
7 hours ago





1




1




$begingroup$
yes :) that would be OK. Let's stop hijacking the comments of this answer now :p
$endgroup$
– dfhwze
7 hours ago





$begingroup$
yes :) that would be OK. Let's stop hijacking the comments of this answer now :p
$endgroup$
– dfhwze
7 hours ago














1












$begingroup$

Inconsistent definition of ExpandoObject. It's IDictionary<string, object> here:




if (p.Value is IDictionary<string, object> dict)

return ConvertDynamicToDictonary(dict); // <- possibly already visited?




and ExpandoObject here:




if (list.Any(o => o is ExpandoObject))

// ..




I would opt to use IDictionary<string, object> both to improve consistency and flexibility of handling instances in the hierarchy.




It is not clear whether the structure of the hierarchical data is a tree or a cyclic graph. This has impact on a possible infinite recursion. In case of a cyclic graph, I would keep track of visited references.




Not all sequences are generic classes.



This condition..




if (p.Value is IEnumerable<object> list)




..does not cover when p.Value is IEnumerable but not IEnumerable<object>. As note in another answer, be careful with false positives (like string).




What if value is null? Try avoiding null reference exceptions in your code.








share|improve this answer











$endgroup$












  • $begingroup$
    Thanks for the ideas. The ExpandoObject should always be a tree since it is just an instance of a class with all traces of null properties removed. This is necessary for correctly invoking some Javascript.
    $endgroup$
    – Joelius
    7 hours ago















1












$begingroup$

Inconsistent definition of ExpandoObject. It's IDictionary<string, object> here:




if (p.Value is IDictionary<string, object> dict)

return ConvertDynamicToDictonary(dict); // <- possibly already visited?




and ExpandoObject here:




if (list.Any(o => o is ExpandoObject))

// ..




I would opt to use IDictionary<string, object> both to improve consistency and flexibility of handling instances in the hierarchy.




It is not clear whether the structure of the hierarchical data is a tree or a cyclic graph. This has impact on a possible infinite recursion. In case of a cyclic graph, I would keep track of visited references.




Not all sequences are generic classes.



This condition..




if (p.Value is IEnumerable<object> list)




..does not cover when p.Value is IEnumerable but not IEnumerable<object>. As note in another answer, be careful with false positives (like string).




What if value is null? Try avoiding null reference exceptions in your code.








share|improve this answer











$endgroup$












  • $begingroup$
    Thanks for the ideas. The ExpandoObject should always be a tree since it is just an instance of a class with all traces of null properties removed. This is necessary for correctly invoking some Javascript.
    $endgroup$
    – Joelius
    7 hours ago













1












1








1





$begingroup$

Inconsistent definition of ExpandoObject. It's IDictionary<string, object> here:




if (p.Value is IDictionary<string, object> dict)

return ConvertDynamicToDictonary(dict); // <- possibly already visited?




and ExpandoObject here:




if (list.Any(o => o is ExpandoObject))

// ..




I would opt to use IDictionary<string, object> both to improve consistency and flexibility of handling instances in the hierarchy.




It is not clear whether the structure of the hierarchical data is a tree or a cyclic graph. This has impact on a possible infinite recursion. In case of a cyclic graph, I would keep track of visited references.




Not all sequences are generic classes.



This condition..




if (p.Value is IEnumerable<object> list)




..does not cover when p.Value is IEnumerable but not IEnumerable<object>. As note in another answer, be careful with false positives (like string).




What if value is null? Try avoiding null reference exceptions in your code.








share|improve this answer











$endgroup$



Inconsistent definition of ExpandoObject. It's IDictionary<string, object> here:




if (p.Value is IDictionary<string, object> dict)

return ConvertDynamicToDictonary(dict); // <- possibly already visited?




and ExpandoObject here:




if (list.Any(o => o is ExpandoObject))

// ..




I would opt to use IDictionary<string, object> both to improve consistency and flexibility of handling instances in the hierarchy.




It is not clear whether the structure of the hierarchical data is a tree or a cyclic graph. This has impact on a possible infinite recursion. In case of a cyclic graph, I would keep track of visited references.




Not all sequences are generic classes.



This condition..




if (p.Value is IEnumerable<object> list)




..does not cover when p.Value is IEnumerable but not IEnumerable<object>. As note in another answer, be careful with false positives (like string).




What if value is null? Try avoiding null reference exceptions in your code.









share|improve this answer














share|improve this answer



share|improve this answer








edited 7 hours ago

























answered 7 hours ago









dfhwzedfhwze

3,9191 gold badge6 silver badges32 bronze badges




3,9191 gold badge6 silver badges32 bronze badges











  • $begingroup$
    Thanks for the ideas. The ExpandoObject should always be a tree since it is just an instance of a class with all traces of null properties removed. This is necessary for correctly invoking some Javascript.
    $endgroup$
    – Joelius
    7 hours ago
















  • $begingroup$
    Thanks for the ideas. The ExpandoObject should always be a tree since it is just an instance of a class with all traces of null properties removed. This is necessary for correctly invoking some Javascript.
    $endgroup$
    – Joelius
    7 hours ago















$begingroup$
Thanks for the ideas. The ExpandoObject should always be a tree since it is just an instance of a class with all traces of null properties removed. This is necessary for correctly invoking some Javascript.
$endgroup$
– Joelius
7 hours ago




$begingroup$
Thanks for the ideas. The ExpandoObject should always be a tree since it is just an instance of a class with all traces of null properties removed. This is necessary for correctly invoking some Javascript.
$endgroup$
– Joelius
7 hours ago











0












$begingroup$

A few minor stylistic bits that may increase its utility:



  • since you take in an IDictionary, return an IDictionary.

  • make it static as it accesses no instance data or methods.

  • since it's now static, make it an extension method.

  • validate the parameter passed in.

Also:



  • since it's a single return statement, make it an expression body.

Further:



  • yeah, the .Any() is redundant (and less performant if there is an ExpandoObject in the collection) with the .Where() criteria, so no need for it.

  • allowed for non-generic IEnumerable.

  • renamed some of the locals to be clearer as to their meaning.

Giving:



static IDictionary<string, object> ConvertDynamicToDictionary(this IDictionary<string, object> source) => source?.ToDictionary(
keySelector => keySelector.Key,
elementSelector =>

object value = elementSelector.Value;

// if it's another IDict (might be a ExpandoObject or could also be an actual Dict containing ExpandoObjects) just go through it recursively
if (value is IDictionary<string, object> dictionary)

return dictionary.ConvertDynamicToDictionary();


// A special case since string implements IEnumerable.
if (value is string stringValue)

return stringValue;


// if it's an IEnumerable, it might have ExpandoObjects inside, so check for that
if (value is IEnumerable enumerable)

// if it does contain ExpandoObjects, take all of those and also go through them recursively
return enumerable
.Cast<object>()
.Select(element => element is IDictionary<string, object> expando
? expando.ConvertDynamicToDictionary()
: element);


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





share|improve this answer











$endgroup$












  • $begingroup$
    Ugh, string implements IEnumerable.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    Clear points, thank you. Yes I already wanted to point out that IEnumerable is used seemingly everywhere and ask if that would cause issues (it would just decrease the performance right?). Also I have edited my question regarding the signature because the method is already private and static I just forgot to write that.
    $endgroup$
    – Joelius
    7 hours ago











  • $begingroup$
    It's not that IEnumerable decreases performance, it's that the .Any() followed by .Where() with the same lambda does the same checking, and therefore .Any() is redundant.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    I see. My edit has now been rolled back because I edited the code which you're not supposed to do. My method is actually private static - would you still recommend me converting it into an extension method?
    $endgroup$
    – Joelius
    7 hours ago










  • $begingroup$
    I mean, I like them. Especially when the parameter is an interface.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago















0












$begingroup$

A few minor stylistic bits that may increase its utility:



  • since you take in an IDictionary, return an IDictionary.

  • make it static as it accesses no instance data or methods.

  • since it's now static, make it an extension method.

  • validate the parameter passed in.

Also:



  • since it's a single return statement, make it an expression body.

Further:



  • yeah, the .Any() is redundant (and less performant if there is an ExpandoObject in the collection) with the .Where() criteria, so no need for it.

  • allowed for non-generic IEnumerable.

  • renamed some of the locals to be clearer as to their meaning.

Giving:



static IDictionary<string, object> ConvertDynamicToDictionary(this IDictionary<string, object> source) => source?.ToDictionary(
keySelector => keySelector.Key,
elementSelector =>

object value = elementSelector.Value;

// if it's another IDict (might be a ExpandoObject or could also be an actual Dict containing ExpandoObjects) just go through it recursively
if (value is IDictionary<string, object> dictionary)

return dictionary.ConvertDynamicToDictionary();


// A special case since string implements IEnumerable.
if (value is string stringValue)

return stringValue;


// if it's an IEnumerable, it might have ExpandoObjects inside, so check for that
if (value is IEnumerable enumerable)

// if it does contain ExpandoObjects, take all of those and also go through them recursively
return enumerable
.Cast<object>()
.Select(element => element is IDictionary<string, object> expando
? expando.ConvertDynamicToDictionary()
: element);


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





share|improve this answer











$endgroup$












  • $begingroup$
    Ugh, string implements IEnumerable.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    Clear points, thank you. Yes I already wanted to point out that IEnumerable is used seemingly everywhere and ask if that would cause issues (it would just decrease the performance right?). Also I have edited my question regarding the signature because the method is already private and static I just forgot to write that.
    $endgroup$
    – Joelius
    7 hours ago











  • $begingroup$
    It's not that IEnumerable decreases performance, it's that the .Any() followed by .Where() with the same lambda does the same checking, and therefore .Any() is redundant.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    I see. My edit has now been rolled back because I edited the code which you're not supposed to do. My method is actually private static - would you still recommend me converting it into an extension method?
    $endgroup$
    – Joelius
    7 hours ago










  • $begingroup$
    I mean, I like them. Especially when the parameter is an interface.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago













0












0








0





$begingroup$

A few minor stylistic bits that may increase its utility:



  • since you take in an IDictionary, return an IDictionary.

  • make it static as it accesses no instance data or methods.

  • since it's now static, make it an extension method.

  • validate the parameter passed in.

Also:



  • since it's a single return statement, make it an expression body.

Further:



  • yeah, the .Any() is redundant (and less performant if there is an ExpandoObject in the collection) with the .Where() criteria, so no need for it.

  • allowed for non-generic IEnumerable.

  • renamed some of the locals to be clearer as to their meaning.

Giving:



static IDictionary<string, object> ConvertDynamicToDictionary(this IDictionary<string, object> source) => source?.ToDictionary(
keySelector => keySelector.Key,
elementSelector =>

object value = elementSelector.Value;

// if it's another IDict (might be a ExpandoObject or could also be an actual Dict containing ExpandoObjects) just go through it recursively
if (value is IDictionary<string, object> dictionary)

return dictionary.ConvertDynamicToDictionary();


// A special case since string implements IEnumerable.
if (value is string stringValue)

return stringValue;


// if it's an IEnumerable, it might have ExpandoObjects inside, so check for that
if (value is IEnumerable enumerable)

// if it does contain ExpandoObjects, take all of those and also go through them recursively
return enumerable
.Cast<object>()
.Select(element => element is IDictionary<string, object> expando
? expando.ConvertDynamicToDictionary()
: element);


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





share|improve this answer











$endgroup$



A few minor stylistic bits that may increase its utility:



  • since you take in an IDictionary, return an IDictionary.

  • make it static as it accesses no instance data or methods.

  • since it's now static, make it an extension method.

  • validate the parameter passed in.

Also:



  • since it's a single return statement, make it an expression body.

Further:



  • yeah, the .Any() is redundant (and less performant if there is an ExpandoObject in the collection) with the .Where() criteria, so no need for it.

  • allowed for non-generic IEnumerable.

  • renamed some of the locals to be clearer as to their meaning.

Giving:



static IDictionary<string, object> ConvertDynamicToDictionary(this IDictionary<string, object> source) => source?.ToDictionary(
keySelector => keySelector.Key,
elementSelector =>

object value = elementSelector.Value;

// if it's another IDict (might be a ExpandoObject or could also be an actual Dict containing ExpandoObjects) just go through it recursively
if (value is IDictionary<string, object> dictionary)

return dictionary.ConvertDynamicToDictionary();


// A special case since string implements IEnumerable.
if (value is string stringValue)

return stringValue;


// if it's an IEnumerable, it might have ExpandoObjects inside, so check for that
if (value is IEnumerable enumerable)

// if it does contain ExpandoObjects, take all of those and also go through them recursively
return enumerable
.Cast<object>()
.Select(element => element is IDictionary<string, object> expando
? expando.ConvertDynamicToDictionary()
: element);


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






share|improve this answer














share|improve this answer



share|improve this answer








edited 7 hours ago

























answered 7 hours ago









Jesse C. SlicerJesse C. Slicer

11.6k27 silver badges40 bronze badges




11.6k27 silver badges40 bronze badges











  • $begingroup$
    Ugh, string implements IEnumerable.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    Clear points, thank you. Yes I already wanted to point out that IEnumerable is used seemingly everywhere and ask if that would cause issues (it would just decrease the performance right?). Also I have edited my question regarding the signature because the method is already private and static I just forgot to write that.
    $endgroup$
    – Joelius
    7 hours ago











  • $begingroup$
    It's not that IEnumerable decreases performance, it's that the .Any() followed by .Where() with the same lambda does the same checking, and therefore .Any() is redundant.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    I see. My edit has now been rolled back because I edited the code which you're not supposed to do. My method is actually private static - would you still recommend me converting it into an extension method?
    $endgroup$
    – Joelius
    7 hours ago










  • $begingroup$
    I mean, I like them. Especially when the parameter is an interface.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago
















  • $begingroup$
    Ugh, string implements IEnumerable.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    Clear points, thank you. Yes I already wanted to point out that IEnumerable is used seemingly everywhere and ask if that would cause issues (it would just decrease the performance right?). Also I have edited my question regarding the signature because the method is already private and static I just forgot to write that.
    $endgroup$
    – Joelius
    7 hours ago











  • $begingroup$
    It's not that IEnumerable decreases performance, it's that the .Any() followed by .Where() with the same lambda does the same checking, and therefore .Any() is redundant.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago










  • $begingroup$
    I see. My edit has now been rolled back because I edited the code which you're not supposed to do. My method is actually private static - would you still recommend me converting it into an extension method?
    $endgroup$
    – Joelius
    7 hours ago










  • $begingroup$
    I mean, I like them. Especially when the parameter is an interface.
    $endgroup$
    – Jesse C. Slicer
    7 hours ago















$begingroup$
Ugh, string implements IEnumerable.
$endgroup$
– Jesse C. Slicer
7 hours ago




$begingroup$
Ugh, string implements IEnumerable.
$endgroup$
– Jesse C. Slicer
7 hours ago












$begingroup$
Clear points, thank you. Yes I already wanted to point out that IEnumerable is used seemingly everywhere and ask if that would cause issues (it would just decrease the performance right?). Also I have edited my question regarding the signature because the method is already private and static I just forgot to write that.
$endgroup$
– Joelius
7 hours ago





$begingroup$
Clear points, thank you. Yes I already wanted to point out that IEnumerable is used seemingly everywhere and ask if that would cause issues (it would just decrease the performance right?). Also I have edited my question regarding the signature because the method is already private and static I just forgot to write that.
$endgroup$
– Joelius
7 hours ago













$begingroup$
It's not that IEnumerable decreases performance, it's that the .Any() followed by .Where() with the same lambda does the same checking, and therefore .Any() is redundant.
$endgroup$
– Jesse C. Slicer
7 hours ago




$begingroup$
It's not that IEnumerable decreases performance, it's that the .Any() followed by .Where() with the same lambda does the same checking, and therefore .Any() is redundant.
$endgroup$
– Jesse C. Slicer
7 hours ago












$begingroup$
I see. My edit has now been rolled back because I edited the code which you're not supposed to do. My method is actually private static - would you still recommend me converting it into an extension method?
$endgroup$
– Joelius
7 hours ago




$begingroup$
I see. My edit has now been rolled back because I edited the code which you're not supposed to do. My method is actually private static - would you still recommend me converting it into an extension method?
$endgroup$
– Joelius
7 hours ago












$begingroup$
I mean, I like them. Especially when the parameter is an interface.
$endgroup$
– Jesse C. Slicer
7 hours ago




$begingroup$
I mean, I like them. Especially when the parameter is an interface.
$endgroup$
– Jesse C. Slicer
7 hours ago










Joelius is a new contributor. Be nice, and check out our Code of Conduct.









draft saved

draft discarded


















Joelius is a new contributor. Be nice, and check out our Code of Conduct.












Joelius is a new contributor. Be nice, and check out our Code of Conduct.











Joelius is a new contributor. Be nice, and check out our Code of Conduct.














Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f223375%2frecursive-conversion-from-expandoobject-to-dictionarystring-object%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

Tom Holland Mục lục Đầu đời và giáo dục | Sự nghiệp | Cuộc sống cá nhân | Phim tham gia | Giải thưởng và đề cử | Chú thích | Liên kết ngoài | Trình đơn chuyển hướngProfile“Person Details for Thomas Stanley Holland, "England and Wales Birth Registration Index, 1837-2008" — FamilySearch.org”"Meet Tom Holland... the 16-year-old star of The Impossible""Schoolboy actor Tom Holland finds himself in Oscar contention for role in tsunami drama"“Naomi Watts on the Prince William and Harry's reaction to her film about the late Princess Diana”lưu trữ"Holland and Pflueger Are West End's Two New 'Billy Elliots'""I'm so envious of my son, the movie star! British writer Dominic Holland's spent 20 years trying to crack Hollywood - but he's been beaten to it by a very unlikely rival"“Richard and Margaret Povey of Jersey, Channel Islands, UK: Information about Thomas Stanley Holland”"Tom Holland to play Billy Elliot""New Billy Elliot leaving the garage"Billy Elliot the Musical - Tom Holland - Billy"A Tale of four Billys: Tom Holland""The Feel Good Factor""Thames Christian College schoolboys join Myleene Klass for The Feelgood Factor""Government launches £600,000 arts bursaries pilot""BILLY's Chapman, Holland, Gardner & Jackson-Keen Visit Prime Minister""Elton John 'blown away' by Billy Elliot fifth birthday" (video with John's interview and fragments of Holland's performance)"First News interviews Arrietty's Tom Holland"“33rd Critics' Circle Film Awards winners”“National Board of Review Current Awards”Bản gốc"Ron Howard Whaling Tale 'In The Heart Of The Sea' Casts Tom Holland"“'Spider-Man' Finds Tom Holland to Star as New Web-Slinger”lưu trữ“Captain America: Civil War (2016)”“Film Review: ‘Captain America: Civil War’”lưu trữ“‘Captain America: Civil War’ review: Choose your own avenger”lưu trữ“The Lost City of Z reviews”“Sony Pictures and Marvel Studios Find Their 'Spider-Man' Star and Director”“‘Mary Magdalene’, ‘Current War’ & ‘Wind River’ Get 2017 Release Dates From Weinstein”“Lionsgate Unleashing Daisy Ridley & Tom Holland Starrer ‘Chaos Walking’ In Cannes”“PTA's 'Master' Leads Chicago Film Critics Nominations, UPDATED: Houston and Indiana Critics Nominations”“Nominaciones Goya 2013 Telecinco Cinema – ENG”“Jameson Empire Film Awards: Martin Freeman wins best actor for performance in The Hobbit”“34th Annual Young Artist Awards”Bản gốc“Teen Choice Awards 2016—Captain America: Civil War Leads Second Wave of Nominations”“BAFTA Film Award Nominations: ‘La La Land’ Leads Race”“Saturn Awards Nominations 2017: 'Rogue One,' 'Walking Dead' Lead”Tom HollandTom HollandTom HollandTom Hollandmedia.gettyimages.comWorldCat Identities300279794no20130442900000 0004 0355 42791085670554170004732cb16706349t(data)XX5557367