I have an ExpandoObject
which is created like so:
public ExpandoObject Get()
{
var expando = new ExpandoObject();
var expandoDic = (IDictionary<string, dynamic>)expando;
// go through the items in the dictionary and copy over the key value pairs)
foreach (var f in GetFieldList())
{
if (f.MaxValues == 1)
{
var val = f.Values.Count > 0 ? f.Values[0] : null;
if (f.displayType == DisplayType.Entity && f.AttachedEntities != null && f.AttachedEntities.Any())
{
if (f.AttachedEntities.Count == 1)
{
expandoDic.Add(new KeyValuePair<string, dynamic>(f.Code, f.AttachedEntities[0].Get()));
}
else
{
expandoDic.Add(new KeyValuePair<string, dynamic>(f.Code, f.AttachedEntities.Select(e => e.Get())));
}
}
else
{
expandoDic.Add(new KeyValuePair<string, dynamic>(f.Code, GetTypedValue(f.GetValueType(), val)));
}
}
else
{
expandoDic.Add(new KeyValuePair<string, dynamic>(f.Code, (dynamic)f.Values.Select(v => GetTypedValue(f.GetValueType(), v))));
}
}
return expando;
}
The GetTypedValue
simply converts the string value into the appropriate type and returns dynamic
.
The problem I'm getting is that if I add a collection to expandoDic
then I can't access the members without casting it to an ICollection
type. Consider the following code, where myPage is an ExpandoObject created by the above method.
Response.Write(myPage.menu.items[0]);
The menu property is a dynamic object, as is items
. The latter is a collection of strings, though the type is actually IEnumerable<dynamic>'. If I inspect myPage.menu.items, it tells me the type is
dynamic {System.Linq.Enumerable.WhereSelectListIterator}`. The above code produces the following error:
Cannot apply indexing with [] to an expression of type 'object'
If I use First()
instead of an index, I instead get this error:
'object' does not contain a definition for 'First'
I understand that I could cast items
to IEnumerable
and fix the problem right away, but I am writing a development framework and want to remove any barriers to developers using it.
I figured out my issue. Where I was creating the IEnumerable of dynamics, I just needed to convert it to an array, like so:
expandoDic.Add(new KeyValuePair<string, dynamic>(f.Code, f.Values.Select(v => GetTypedValue(f.GetValueType(), v)).ToArray()));
This proves yet again that having to explain the problem thoroughly can often reveal the answer.