gpt4 book ai didi

C# 反射表达式 Linq

转载 作者:行者123 更新时间:2023-11-30 14:21:39 25 4
gpt4 key购买 nike

我在使用 C# 动态生成的 lambda 表达式时遇到一些问题。

考虑以下场景:

public class Person {
public long Id { get; set; }
public string Name { get; set; }
}

List<Person> persons = new List<Person> () {
new Person { Id = 1, Name = "Foo" },
new Person { Id = 2, Name = "Bar" },
new Person { Id = 3, Name = "Baz" },
new Person { Id = 4, Name = null },
};

现在,执行以下代码

ParameterExpression param = Expression.Parameter(typeof(Person), "arg");
Expression prop = Expression.Property(param, "Name");
Expression value = Expression.Constant("bar");
Type type = prop.Type;

MethodInfo toLower = typeof(String).GetMethod("ToLower", Type.EmptyTypes);
Expression expLower = Expression.Call(prop, toLower);

Expression clausule = Expression.Call(expLower, type.GetMethod("Contains", new[] { type }), value);
Expression notNull = Expression.NotEqual(prop, Expression.Constant(null));

clausule = Expression.And(notNull, clausule);

var exp = Expression.Lambda<Func<T, bool>>(clausule, param);

上面的代码生成下面的表达式。

//arg => ((arg.Name != null) And (arg.Name.ToLower().Contains("bar")))

现在,尝试将其应用到我的列表中。

下面的过滤器有效

var filteredListThatWorks = persons.Where(arg => arg.Name != null && arg.Name.ToLower().Contains("bar")).ToList();

下面的抛出 Null 对象的异常(因为 Id 4 名称)

var filteredListThatGivesExp = persons.Where(exp.Compile()).ToList();

相同的表达式,当由 lambda 生成时,会抛出 exp,当手动输入时,它会起作用。有谁知道解决这个问题的方法吗?

最佳答案

And&;你想使用 AndAlso (&&):

clausule = Expression.AndAlso(notNull, clausule);

如有疑问,sharplab.io 是一个很好的工具;如果我使用:

Expression<Func<Person, bool>> filter
= arg => arg.Name != null && arg.Name.ToLower().Contains("bar");

它告诉我它编译后等同于:

// ...
BinaryExpression body = Expression.AndAlso(left, Expression.Call(instance, method, obj));
// ...

(请注意,它必须对一些指令说谎,因为它编译成实际上无法用原始 C# 表达的东西)

see it in action

关于C# 反射表达式 Linq,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53445071/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com