简体   繁体   中英

How to use Expression.MakeIndex in Linq Expressions?

Property indexer array

trying to dynamically generate the following lambda expression:

Expression<Func<Program, string>> y = _ => _.x[0];

Where x is of type List

Attempting to use Expression.MakeIndex, but it seems to be bouncing an exception:

Expression.MakeIndex(parameter, typeof (Program).GetProperty("x"), new[] {Expression.Constant(0)})

The exception message:

Incorrect number of arguments supplied for call to method 'System.Collections.Generic.List`1[System.String] get_x()'

How can I make this right?

There are two operations going on here:

  1. Get x from parameter
  2. Access item at index 0

You need to create two separate expressions for this:

var property = Expression.Property(parameter, typeof (Program).GetProperty("x"));
var itemAtPosition0 = Expression.MakeIndex(property, typeof(List<string>).GetProperty("Item"),
                     new [] { Expression.Constant(0) });

"Item" refers to the default name of the indexer property. For more information about this name and how to reliably detect the actual name used, have a look at this answer .

This answer assumes that the Program class is defined like this:

public class ProgramZ
{
    public List<string> x { get; set; }
}

The problem is that you are trying to applying the indexing to the Program.x property, when it really should be applied to the List<string> 's indexer property (which is called Item ).

In the end, to be able to Invoke the expression you need to wrap it into a lambda.

Here's the code to do that:

var expr =
    Expression.Lambda<Func<Program, string>>(
        Expression.MakeIndex(
                Expression.Property(
                    parameter,
                    typeof(Program).GetProperty("x")),
                typeof(List<string>).GetProperty("Item"),
                new[] { Expression.Constant(0) }),
        parameter);

And here's how to invoke the expression:

var instance = new ProgramZ { x = new List<string> { "a", "b" } };

Console.WriteLine(expr.Compile().Invoke(instance));

This code will output a , as expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM