为可空枚举动态构建谓词

Posted

技术标签:

【中文标题】为可空枚举动态构建谓词【英文标题】:Dynamically build a predicate for a nullable enum 【发布时间】:2018-01-22 16:29:55 【问题描述】:

我正在尝试动态构建搜索谓词,但我的班级中的可空枚举存在一些问题。

这是我的类和枚举结构:

public class TestNullableEnumClass

    public TestingEnum? TestEn  get; set; 


public enum TestingEnum

    [Description("Item 1")]
    Item1,
    [Description("Item 2")]
    Item2,
    [Description("Item 3")]
    Item3,
    [Description("Item 4")]
    Item4,
    [Description("Item 5")]
    Item5

我现在创建一个类列表,其中一个类的枚举值为空:

List<TestNullableEnumClass> myList = new List<TestNullableEnumClass>();

myList.Add(new TestNullableEnumClass  TestEn = TestingEnum.Item1 );
myList.Add(new TestNullableEnumClass   );

IQueryable<TestNullableEnumClass> query = myList.AsQueryable();

我现在想动态创建一个表达式来过滤 TestNullableEnumClass 将属性 TestEn 设置为 TestingEnum.Item1 的列表。

var predicate = PredicateBuilder.New<TestNullableEnumClass>();

var parameter = Expression.Parameter(typeof(TestNullableEnumClass), typeof(TestNullableEnumClass).Name);
Expression member = Expression.Property(parameter, type.Name);
var constant = Expression.Constant(TestingEnum.Item1);
var body = Expression.Equal(member, constant);
var expression = Expression.Lambda<Func<TestNullableEnumClass, bool>>(body, parameter);

predicate.Or(expression);

上述代码在 Expression.Equal 行上失败,并出现以下错误:

"二元运算符 Equal 没有为类型 'System.Nullable`1[ExpressionTest.TestingEnum]' 和 'ExpressionTest.TestingEnum' 定义。"

如果我将属性 TestEn 设置为请求字段,我的代码就可以正常工作。

我需要添加什么才能使其与可空枚举一起使用?

我正在有效地尝试动态编写以下内容:

var list = query.Where(x => x.TestEn.Equals(TestingEnum.Item1)).ToList();

【问题讨论】:

只需将ExpressionTest.TestingEnum 包裹在System.Nullable[ExpressionTest.TestingEnum] 中,这样比较的两边都是System.Nullable[ExpressionTest.TestingEnum] ExpressionTest.TestingEnum 是命名空间和枚举定义!如何将其包装为 Nullable 类型? TestingEnum?System.Nullable&lt;TestingEnum&gt; 的语法糖。 相信你只需要写Expression.Constant((TestingEnum?)TestingEnum.Item1) 不,仍然会导致同样的错误 【参考方案1】:

您需要将常量转换为成员变量的类型。

var predicate = PredicateBuilder.New<TestNullableEnumClass>();

var parameter = Expression.Parameter(typeof(TestNullableEnumClass), typeof(TestNullableEnumClass).Name);
Expression member = Expression.Property(parameter, type.Name);
var constant = Expression.Constant(TestingEnum.Item1);
var constantConverted = Expression.Convert(constant, member.Type);
var body = Expression.Equal(member, constantConverted);
var expression = Expression.Lambda<Func<TestNullableEnumClass, bool>>(body, parameter);

predicate.Or(expression);

【讨论】:

那是完美的。谢谢。

以上是关于为可空枚举动态构建谓词的主要内容,如果未能解决你的问题,请参考以下文章

附加 QueryDSL 谓词或基于过滤器值构建谓词

NSPredicate - 带参数的动态谓词

创建没有下推谓词的动态框架问题

SwiftUI 中的动态过滤器(谓词)

Linq In 子句和谓词构建

如何在 Java 中动态构造谓词