Problem
我正在重构一些LINQ
查询我们的 Web 应用程序中的多个报告,并且我尝试将一些重复的查询谓词移至它们自己的中IQueryable
扩展方法,以便我们可以将它们重新用于这些报告以及将来的报告。正如您可能推断的那样,我已经重构了组的谓词,但是代码的谓词给我带来了问题。这是我迄今为止所拥有的一种报告方法的示例:
达尔法:
public List<Entities.QueryView> GetQueryView(Filter filter)
{
using (var context = CreateObjectContext())
{
return (from o in context.QueryViews
where (!filter.FromDate.HasValue || o.RepairDate >= EntityFunctions.TruncateTime(filter.FromDate))
&& (!filter.ToDate.HasValue || o.RepairDate <= EntityFunctions.TruncateTime(filter.ToDate))
select o)
.WithCode(filter)
.InGroup(filter)
.ToList();
}
}
IQueryable
扩大:
public static IQueryable<T> WithCode<T>(this IQueryable<T> query, Filter filter)
{
List<string> codes = DAL.GetCodesByCategory(filter.CodeCategories);
if (codes.Count > 0)
return query.Where(Predicates.FilterByCode<T>(codes));
return query;
}
谓词:
public static Expression<Func<T, List<string>, bool>> FilterByCode<T>(List<string> codes)
{
// Method info for List<string>.Contains(code).
var methodInfo = typeof(List<string>).GetMethod("Contains", new Type[] { typeof(string) });
// List of codes to call .Contains() against.
var instance = Expression.Variable(typeof(List<string>), "codes");
var param = Expression.Parameter(typeof(T), "j");
var left = Expression.Property(param, "Code");
var expr = Expression.Call(instance, methodInfo, Expression.Property(param, "Code"));
// j => codes.Contains(j.Code)
return Expression.Lambda<Func<T, List<string>, bool>>(expr, new ParameterExpression[] { param, instance });
}
我遇到的问题是Queryable.Where
不接受某种类型Expression<Func<T, List<string>, bool>
。我能想到动态创建这个谓词的唯一方法是使用两个参数,这是真正困扰我的部分。
我不明白的是以下方法有效。我可以传递我尝试动态创建的精确 lambda 表达式,并且它可以正确过滤我的数据。
public List<Entities.QueryView> GetQueryView(Filter filter)
{
// Get the codes here.
List<string> codes = DAL.GetCodesByCategory(filter.CodeCategories);
using (var context = CreateObjectContext())
{
return (from o in context.QueryViews
where (!filter.FromDate.HasValue || o.RepairDate >= EntityFunctions.TruncateTime(filter.FromDate))
&& (!filter.ToDate.HasValue || o.RepairDate <= EntityFunctions.TruncateTime(filter.ToDate))
select o)
.Where(p => codes.Contains(p.Code)) // This works fine.
//.WithCode(filter)
.InGroup(filter)
.ToList();
}
}
问题
- 我可以自己实现吗
Queryable.Where
超载?如果是的话,这是否可行?
- 如果重载不可行,是否有办法动态构造谓词
p => codes.Contains(p.Code)
不使用两个参数?
- 有没有更简单的方法来做到这一点?我觉得我失去了一些东西。