属性索引器数组
尝试动态生成以下lambda表达式:
Expression<Func<Program, string>> y = _ => _.x[0];
其中x的类型为List
尝试使用Expression.MakeIndex,但它似乎反弹异常:
Expression.MakeIndex(parameter, typeof (Program).GetProperty("x"), new[] {Expression.Constant(0)})
异常消息:
为方法调用提供的参数数量不正确 'System.Collections.Generic.List`1 [System.String] get_x()'
我怎样才能做到这一点?
答案 0 :(得分:5)
这里有两个操作:
x
parameter
您需要为此创建两个单独的表达式:
var property = Expression.Property(parameter, typeof (Program).GetProperty("x"));
var itemAtPosition0 = Expression.MakeIndex(property, typeof(List<string>).GetProperty("Item"),
new [] { Expression.Constant(0) });
"Item"
是指索引器属性的默认名称。有关此名称以及如何可靠地检测实际名称的更多信息,请查看this answer。
答案 1 :(得分:3)
这个答案假定Program
类的定义如下:
public class ProgramZ
{
public List<string> x { get; set; }
}
问题是您正在尝试将索引应用于Program.x
属性,当它确实应该应用于List<string>
的索引器属性(称为Item
)时
最后,为了能够调用表达式,你需要将它包装成lambda。
以下是执行此操作的代码:
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);
以下是调用表达式的方法:
var instance = new ProgramZ { x = new List<string> { "a", "b" } };
Console.WriteLine(expr.Compile().Invoke(instance));
此代码将按预期输出a
。