Search code examples
c#.netexpression-trees

Accessing elements of types with indexers using expression trees


Suppose I have a type like this:

class Context
{
    SomeType[] Items { get; set; }
}

I want to be able to access specific Items elements using expression trees. Suppose I need an element at index 0. I can do it like below, where everything works as expected:

var type = typeof (Context);
var param = Expression.Parameter(typeof (object));
var ctxExpr= Expression.Convert(param, context);    
var proInfo = type.GetProperty("Items");

Expression.ArrayIndex(Expression.Property(ctxExpr, proInfo), Expression.Constant(0));

If I change the context type to contain .NET provided List<SomeType>, instead of array, i.e.

class Context
{
    List<SomeType> Items { get; set; }
}

the same expression results in following error:

System.ArgumentException: Argument must be array at System.Linq.Expressions.Expression.ArrayIndex(Expression array, Expression index)

My question is, how to write respective expression which can access an item under appropriate index of List<>, or better - of any collection declaring indexer? E.g. is there is some way to detect, and convert such a collection to an array of appropriate types using expression trees?


Solution

  • An indexer is really just a property with an extra parameter, so you want:

    var property = Expression.Property(ctxExpr, proInfo);
    var indexed = Expression.Property(property, "Item", Expression.Constant(0));
    

    where "Item" is the name of the indexed property here.

    (If you don't know the name of the property beforehand, it's usually Item but you can always find it via reflection, by finding all properties with indexer parameters.)