我想提供一组过滤器供用户选择,每个过滤器都对应一个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)
我不明白为什么(或者甚至是如何)它仍在查看某些匿名类型,即使我使用的是声明为字符串的局部变量.有没有办法按照我的意愿来完成这项工作?
anon-type实际上是用于执行变量捕获的编译器生成的类型.对于代理,您可以通过手动实现捕获来解决这个问题,但不能将lambda表达式编译为表达式树.
两种选择:
后者实际上并不太糟糕; 它们通常只是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)