逻辑逆Func <T,bool>

Dav*_*vid 4 c# linq func expression-trees linq-expressions

我的代码库中有一些相当复杂的实体框架查询,我决定将逻辑集中到模型中.基本上,描绘了一堆控制器,它们在表达式树中有大量查询和大量重复代码.因此,我取出了部分表达树并将它们移动到模型中,从而减少了重复次数.

例如,假设我经常需要获取名为Entity的模型,这些模型处于Not Deleted状态.在我的实体模型上,我有:

public static Func<Entity, bool> IsNotDeleted = e =>
    e.Versions != null ?
        e.Versions.OrderByDescending(v => v.VersionDate).FirstOrDefault() != null ?
            e.Versions.OrderByDescending(v => v.VersionDate).First().ActivityType != VersionActivityType.Delete :
            false :
       false;
Run Code Online (Sandbox Code Playgroud)

(这是较小的示例之一,主要是在尝试检查数据之前检查有效数据.)

使用它看起来像:

var entities = EntityRepository.Entities.Where(Entity.IsNotDeleted).Where(...
Run Code Online (Sandbox Code Playgroud)

但是我发现,虽然有时候我想这是不会被删除的记录,其他时间我想要的记录删除.要做到这一点,有没有办法从消费代码中反转逻辑?概念上类似于此的东西(显然不起作用):

var entities = EntityRepository.Entities.Where(!Entity.IsDeleted).Where(...
Run Code Online (Sandbox Code Playgroud)

我宁愿不在Func<>物体上有两个,一个用于IsDeleted,另一个IsNotDeleted几乎相同.的Func<>回报bool,是否有语法把一个在当它调用它的逆.Where()条款?

Tim*_*lds 12

请考虑以下扩展方法.

public static class Functional
{
    public static Func<T, bool> Not<T>(this Func<T, bool> f)
    {
        return x => !f(x);
    }

    public static Expression<Func<T, bool>> Not<T>(
        this Expression<Func<T, bool>> f)
    {
        // 1. Break the lambda f apart into its parameters and body.
        // 2. Wrap the body expression with a unary not expression (!).
        // 3. Construct a new lambda with the modified body.
        return Expression.Lambda<Func<T, bool>>(
            Expression.Not(f.Body), f.Parameters);
    }
}
Run Code Online (Sandbox Code Playgroud)

Entity.IsDeleted.Not()是一样的Entity.IsNotDeleted().

请注意,您可能希望使用Expression<Func<T, bool>>- 而不是Func<T, bool>- 因此您的lambda逻辑可以在数据库端而不是客户端使用.

你可以像这样使用它:

Expression<Func<int, bool>> isNegative = x => x < 0;
Expression<Func<int, bool>> isNonNegative = isNegative.Not();
Run Code Online (Sandbox Code Playgroud)