我在使用C#动态生成的lambda表达式时遇到了一些问题. 考虑以下情况: public class Person { public long Id { get; set; } public string Name { get; set; }}ListPerson persons = new ListPerson () { new Person { Id = 1, Na
考虑以下情况:
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);
上面的代码生成以下exp.
//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.
有谁知道解决这个问题的方法?
BR,
并且是& ;;你想使用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