Cannot apply indexing with [] to an expression of type 'object' (even though the type is 'dynamic')

Maloric picture Maloric · Feb 28, 2014 · Viewed 9.1k times · Source

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 isdynamic {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.

Answer

Fedor Hajdu picture Fedor Hajdu · Feb 28, 2014

For dynamic types you cannot use the extension method without conversion, but you can use static call of the method so instead of:

var a = yourDynamic.First();

you should write

var a = Enumerable.First(yourDynamic);