9

我在基类中有一个 WhereFilter 属性,如下所示:

public virtual Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return null; }
}

当它被覆盖时,我想返回其他内容而不是 null 以便我可以使用谓词构建器扩展 And (来自LinqKit)所以我可以编写如下代码:

public override Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return base.WhereFilter.And(x => x.CustomerID == 1); }
}

但这会产生错误,因为 WhereFilter 为空(对象引用未设置为对象的实例)。

目前我正在写作:

public override Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return x => x.CustomerID == 1; }
}

因此,当有另一个子类覆盖它时,基类属性将丢失。

有什么办法可以解决这个问题?在 sql 中我所做的是使用 1=1 的虚拟对象,这可以在 linq 中类似地完成吗?

4

4 回答 4

19

LINQ 相当于 SQL 的1=1“thingy”是一个始终返回 true 的谓词:

x => true

更改默认方法如下:

public virtual Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get { return x=>true; }
}
于 2013-09-03T13:16:34.200 回答
5

您可以简单地检查继承的属性是否返回null

public override Expression<Func<CustomerCustomerType, bool>> WhereFilter
{
    get {
        var baseResult = base.WhereFilter;
        if (baseResult == null) {
            return x => x.CustomerID == 1;
        } else {
            return base.WhereFilter.And(x => x.CustomerID == 1);
        }
    }
}

IMO 这将比看似毫无意义的虚拟值更具可读性,这将使您(或任何其他使用该代码的人)在以后想知道那是什么。(而且它甚至可能会在运行时减少一点点开销。)

如果您坚持使用较少的行数,您可以使用运算符缩短if-表达式。else?:


编辑:进一步考虑这一点,您可能会将其视为一个缺点,即每个覆盖该属性的人都必须编写如此多的代码,这可能会引入错误。但是,在调用继承的代码时依赖不包含任何此类错误的覆盖方法是一个值得怀疑的设计选择,就像您提出的模型一样,覆盖器也可能只返回其新谓词而不调用And.

一个更简洁的设计,IMO,将创建虚拟属性protected,并让它只返回新的谓词(或null)。然后,可公开访问的(和非虚拟的)属性将负责检索当前和任何超类的任何谓词,并将它们与And多个谓词结合起来。

于 2013-09-03T13:17:09.133 回答
2

您可以执行以下操作:

    public virtual Expression<Func<CustomerCustomerType, bool>> WhereFilter    
    {
        get { return customerCustomerType => true; }
    }

这是一个始终返回 true 的表达式。

于 2013-09-03T13:20:56.727 回答
0

如果您在调试中,则不能使用 lambda 表达式 (EF),您可以使用它来欺骗 linq,如果您使用标准 linq,请在结尾处使用带有 .Compile() 的这句话:

表达式>.Lambda(Expression.Constant(true),Expression.Parameter(typeof(T)))

于 2014-09-23T20:27:04.523 回答