【问题标题】:How to use Expression.MakeIndex in Linq Expressions?如何在 Linq 表达式中使用 Expression.MakeIndex?
【发布时间】:2018-07-11 15:09:04
【问题描述】:

属性索引器数组

尝试动态生成以下 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()'

我怎样才能做到这一点?

【问题讨论】:

  • “似乎正在反弹异常”。好吧,你似乎忘了告诉我们是哪一个 - 以及它包含什么信息......

标签: c# .net linq expression


【解决方案1】:

这里有两个操作:

  1. parameter 获取x
  2. 访问索引 0 处的项目

您需要为此创建两个单独的表达式:

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

【讨论】:

  • 谢谢,这个链接也回答了我的另一个问题——如果它总是“项目”,为什么要创建一个可以传递另一个名称的参数。
  • 感谢您的解决方案 - 经过数小时的尝试后完美运行。但是,直到我重新分配回“property = Expression.make....”,它才起作用。如果您可以更新答案,请不胜感激。
  • 好吧,显然你需要将MakeIndex 的结果分配给一个变量才能实际使用它...
【解决方案2】:

此答案假定 Program 类的定义如下:

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

问题是您试图将索引应用于Program.x 属性,而实际上它应该应用于List&lt;string&gt; 的索引器属性(称为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

【讨论】:

    猜你喜欢
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多