使用匿名类型构建表达式

Mik*_*uck 5 c# linq linq-to-sql predicatebuilder

假设我通过 LINQ 查询创建了一些匿名类型:

var query = from Person in db.People
            join Pet in Pets on Person.ID equals Pet.PersonID
            join Thingy in Thingies on Person.ID equals Thingy.PersonID
            select new { 
                Person.ID, 
                PetName = Pet.Name,
                Thing = Thingy.Thing,
                OtherThing = Thingy.OtherThing
            };
Run Code Online (Sandbox Code Playgroud)

现在我想通过动态构建谓词将一些复杂的表达式应用于查询。我对已知类型所做的事情是这样的:

var predicate = PredicateBuilder.False<MyType>();
predicate = predicate.Or(myType => myType.Flag);
if (someCondition) {
    var subPredicate = PredicateBuilder.True<MyType>();
    subPredicate = subPredicate.And(myType => myType.Thing == someThing);
    subPredicate = subPredicate.And(myType => myType.OtherThing == someOtherThing);
    predicate = predicate.Or(subPredicate);
}
query = query.Where(predicate);
Run Code Online (Sandbox Code Playgroud)

是否可以对匿名类型做类似的事情?我还没有找到一种使用匿名类型的方法,PredicateBuilder我也不熟悉任何其他可以让我动态构建这样的表达式的构造。如果没有,在为查询动态生成嵌套表达式时,我应该采用另一种方法吗?

das*_*ght 6

假设所有你需要的是PredicateBuilder.False<T>PredicateBuilder.True<T>一个匿名类型,你可以做这样的:

private static Expression<Func<T,bool>> MakeTrue<T>(IQueryable<T> ignored) {
    return PredicateBuilder.True<T>();
}
private static Expression<Func<T,bool>> MakeFalse<T>(IQueryable<T> ignored) {
    return PredicateBuilder.False<T>();
}
Run Code Online (Sandbox Code Playgroud)

现在,您无需显式使用匿名类型即可重写代码:

var predicate = MakeFalse(query);
predicate = predicate.Or(v => v.ID > 10000);
query = query.Where(predicate);
Run Code Online (Sandbox Code Playgroud)

这个想法是让编译器为你做类型推断。不幸的是,您最终会得到一个未使用的方法参数。