patterncsharpMinor
Finding elements inside ExpandoObject
Viewed 0 times
insideexpandoobjectelementsfinding
Problem
Is it possible to simplify the code below?
Maybe it is possible to implement similar logic with Linq? Any thoughts?
dynamic model = GetExpandoObject(); //model type of ExpandoObject
var result = model.FirstOrDefault(x => x.Key == "node").Value;
if (result != null)
{
result = ((ExpandoObject)result).FirstOrDefault(x => x.Key == "children");
if (result != null)
{
result = ((IList)((KeyValuePair)result).Value).FirstOrDefault();
if (result != null)
{
if (result != null)
{
result = ((ExpandoObject)result).FirstOrDefault(x => x.Key == "node").Value;
if (result != null)
{
result = ((ExpandoObject)result).FirstOrDefault(x => x.Key == "stuff");
}
}
}
}
}Maybe it is possible to implement similar logic with Linq? Any thoughts?
Solution
In your code, the variable result is just of type
Below I've used explicit typing using
I created this extension method so that you wouldn't have to cast the object everytime you wanted to use it... this takes care of that before it returns
What follows is a re-implementation of the original post's code using the above method
What follows is another possible implementation using nested
Update:
Using a newer feature of C# null-propagation, we can string all these calls together. Now we no longer need to save each object down the chain (unless we want to).
Here is an implementation using null-propagation.
object because the compiler doesn't know what the result of FirstOrDefault is going to be.Below I've used explicit typing using
T for clarity and so that var doesn't evaluate to objectI created this extension method so that you wouldn't have to cast the object everytime you wanted to use it... this takes care of that before it returns
public static class ExtensionMethods
{
public static T FirstOrDefault(this ExpandoObject eo, string key)
{
object r = eo.FirstOrDefault(x => x.Key == key).Value;
return (r is T) ? (T)r : default(T);
}
}What follows is a re-implementation of the original post's code using the above method
ExpandoObject model = GetExpandoObject();
var someExpandoObject = model.FirstOrDefault("node");
if (someExpandoObject == null) return;
var kvp = someExpandoObject.FirstOrDefault>("children");
if (kvp.Equals(default(KeyValuePair))) return;
var ilo = kvp.Value as IList;
if (ilo == null) return;
someExpandoObject = ilo.FirstOrDefault() as ExpandoObject;
if (someExpandoObject == null) return;
someExpandoObject = someExpandoObject.FirstOrDefault("node");
if (someExpandoObject == null) return;
object finalResult = someExpandoObject.FirstOrDefault("stuff");What follows is another possible implementation using nested
if statements instead of multiple return statements.ExpandoObject model = GetExpandoObject();
ExpandoObject someExpandoObject;
KeyValuePair kvp;
IList ilo;
object finalResult;
if ((someExpandoObject = model.FirstOrDefault("node")) != null)
{
if (!(kvp = someExpandoObject.FirstOrDefault>("children")).Equals(default(KeyValuePair)))
{
if ((ilo = kvp.Value as IList) != null)
{
if ((someExpandoObject = ilo.FirstOrDefault() as ExpandoObject) != null)
{
if ((someExpandoObject = someExpandoObject.FirstOrDefault("node")) != null)
finalResult = someExpandoObject.FirstOrDefault("stuff");
}
}
}
}Update:
Using a newer feature of C# null-propagation, we can string all these calls together. Now we no longer need to save each object down the chain (unless we want to).
Here is an implementation using null-propagation.
object finalResult = ((model.FirstOrDefault("node")
?.FirstOrDefault>("children").Value as IList)
?.FirstOrDefault() as ExpandoObject)
?.FirstOrDefault("stuff");Code Snippets
public static class ExtensionMethods
{
public static T FirstOrDefault<T>(this ExpandoObject eo, string key)
{
object r = eo.FirstOrDefault(x => x.Key == key).Value;
return (r is T) ? (T)r : default(T);
}
}ExpandoObject model = GetExpandoObject();
var someExpandoObject = model.FirstOrDefault<ExpandoObject>("node");
if (someExpandoObject == null) return;
var kvp = someExpandoObject.FirstOrDefault<KeyValuePair<string, object>>("children");
if (kvp.Equals(default(KeyValuePair<string, object>))) return;
var ilo = kvp.Value as IList<object>;
if (ilo == null) return;
someExpandoObject = ilo.FirstOrDefault() as ExpandoObject;
if (someExpandoObject == null) return;
someExpandoObject = someExpandoObject.FirstOrDefault<ExpandoObject>("node");
if (someExpandoObject == null) return;
object finalResult = someExpandoObject.FirstOrDefault<object>("stuff");ExpandoObject model = GetExpandoObject();
ExpandoObject someExpandoObject;
KeyValuePair<string, object> kvp;
IList<object> ilo;
object finalResult;
if ((someExpandoObject = model.FirstOrDefault<ExpandoObject>("node")) != null)
{
if (!(kvp = someExpandoObject.FirstOrDefault<KeyValuePair<string, object>>("children")).Equals(default(KeyValuePair<string, object>)))
{
if ((ilo = kvp.Value as IList<object>) != null)
{
if ((someExpandoObject = ilo.FirstOrDefault() as ExpandoObject) != null)
{
if ((someExpandoObject = someExpandoObject.FirstOrDefault<ExpandoObject>("node")) != null)
finalResult = someExpandoObject.FirstOrDefault<object>("stuff");
}
}
}
}object finalResult = ((model.FirstOrDefault<ExpandoObject>("node")
?.FirstOrDefault<KeyValuePair<string, object>>("children").Value as IList<object>)
?.FirstOrDefault() as ExpandoObject)
?.FirstOrDefault<object>("stuff");Context
StackExchange Code Review Q#43400, answer score: 8
Revisions (0)
No revisions yet.