LINQ:如何强制基于值的引用?

Ste*_*ven 6 .net c# linq

我想提供一组过滤器供用户选择,每个过滤器都对应一个Expression<Func<X, bool>>.因此,我可能想要获取可用项目的动态列表('Joe','Steve','Pete'等),并根据这些名称创建一组"硬编码"过滤器,并让用户选择他想要使用哪个过滤器.我的问题是,即使我尝试根据动态列表中的字符串值"硬编码"我的表达式,表达式仍然存储值为,看起来是什么,一个悬挂在匿名类型上的属性(和我不知道如何序列化anon.类型).对不起,如果这令人困惑,我不太清楚如何表达这一点.

这是我的示例代码:

    public class Foo
    {
        public string Name { get; set; }
    }
    static void Main(string[] args)
    {
        Foo[] source = new Foo[]
            {
                new Foo() { Name = "Steven" } ,
                new Foo() { Name = "John" } ,
                new Foo() { Name = "Pete" },
            };

            List<Expression<Func<Foo, bool>>> filterLst = new List<Expression<Func<Foo, bool>>>();
            foreach (Foo f in source)
            {
                Expression<Func<Foo, bool>> exp = x => x.Name == f.Name;
                filterLst.Add(exp);
            }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,当我看到表达的主体时,它看起来如下:

(x.Name = value(ConsoleApplication1.Program+<>c__DisplayClass3).value)
Run Code Online (Sandbox Code Playgroud)

当我真正想要的是第一个读到这样的:

(x.Name = "Steven")
Run Code Online (Sandbox Code Playgroud)

(如果我将代码改为此代码,那就是我得到的:

      Expression<Func<Foo, bool>> exp = x => x.Name == "Steven";
Run Code Online (Sandbox Code Playgroud)

)

我已经尝试将我的值强制为本地字符串值,然后将其粘贴到Expression中,但它似乎没有帮助:

    List<Expression<Func<Foo, bool>>> filterLst = new List<Expression<Func<Foo, bool>>>();
    foreach (Foo f in source)
    {
        string value = f.Name;
        Expression<Func<Foo, bool>> exp = x => x.Name == value;
        filterLst.Add(exp);
    }
Run Code Online (Sandbox Code Playgroud)

我不明白为什么(或者甚至是如何)它仍在查看某些匿名类型,即使我使用的是声明为字符串的局部变量.有没有办法按照我的意愿来完成这项工作?

Mar*_*ell 7

anon-type实际上是用于执行变量捕获的编译器生成的类型.对于代理,您可以通过手动实现捕获来解决这个问题,但不能将lambda表达式编译为表达式树.

两种选择:

  • 通过Expression.Constant等在代码上明确地构建表达式树
  • 学习如何处理匿名类型

后者实际上并不太糟糕; 它们通常只是MemberExpression,虽然我有一些代码在全面详细介绍.我还可以提供构建表达式树的示例,但我现在不在PC上,它不适合iPod打字......

简短的问题解读,我会看第一个选项而不是第二个选项.

哦,小心; 问题中的第一个 foreach代码看起来容易受到臭名昭着的l值捕获问题的影响;)


编辑:我发现了一台PC; p

        var param = Expression.Parameter(typeof(Foo), "x");
        var body = Expression.Equal(
            Expression.PropertyOrField(param, "Name"),
            Expression.Constant(f.Name, typeof(string)));

        var exp = Expression.Lambda<Func<Foo, bool>>(body, param);
        filterLst.Add(exp);
Run Code Online (Sandbox Code Playgroud)