c# - .Net 领域的动态查询构建器
问题描述
我正在使用 Realm 数据库在我的设备上本地存储数据。在应用程序中,用户可以查看书籍列表并对其应用过滤器/排序。一本书是一个 Pojo 对象,它具有标题、作者(字符串)、状态(枚举)和发布日期(时间戳)。应用程序的用户可以根据这四个字段过滤书籍,对象上有更多字段,但为简单起见,我目前只使用 4 个。
我正在尝试创建一个动态查询构建器,其中所有选定的过滤器都将应用于查询。
我在文档中看到的是我们可以像这样查询领域
var allBooks = realm.All<Book>().Where(book =>
book.Title== "Star wars" ||
book.Status== "Sold");
我想要的是通过将过滤器列表传递给方法来自己构建查询。我正在考虑使用键/值对创建一个包装器类并分配过滤器的名称和值。然后我可以将这些列表传递给一个方法。我的问题是如何从键/值列表构建查询构建器,其中键是对象字段,如“标题”、“状态”,值是“星球大战”、“已售”。
任何帮助将不胜感激。
解决方案
您可以使用 Linq 表达式创建动态谓词:
public static Expression<Func<T, bool>> CreatePredicate<T>(KeyValuePair<string, string>[] filters)
{
var type = typeof(T);
var parameter = Expression.Parameter(type, "t");
if (filters.Length == 0) // no filtering
return Expression.Lambda<Func<T, bool>>(Expression.Constant(true), parameter);
Expression body = Expression.Constant(false);
foreach (var filter in filters)
{
var member = Expression.PropertyOrField(parameter, filter.Key);
var value = Expression.Constant(filter.Value);
body = Expression.OrElse(body, Expression.Equal(member, value));
}
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
现在如果All<Book>()
返回一个IQueryable<Book>
使用它:
var predicate = CreatePredicate<Book>(new[]
{
new KeyValuePair<string, string>("Title", "Star wars"),
new KeyValuePair<string, string>("Status", "Sold"),
});
var allBooks = realm.All<Book>().Where(predicate);
如果All<Book>()
返回IEnumerable<Book>
您仍然可以使用它,只需添加调用Compile
:
var allBooks = realm.All<Book>().Where(predicate.Compile());
推荐阅读
- sql - 添加使用 MAX 的计算列
- wordpress - Wordpress 儿童主题入队、出队和本地化
- python - 在 DataFrame 列中计算 NaN 窗口(及其大小)
- javascript - Apollo MockedProvider 测试问题(我渲染的组件不断消失)
- r - R不承认导入表的科学计数法?
- python-3.x - 如何在 for 循环中执行显式等待元素?
- angular - 单击复选框时未传递更改事件
- redux - 使用 Jest 进行 React-Redux 测试:收到的有效负载 = 未定义
- unity3d - 为什么启动画面不显示?
- c# - 使用 PanGestureRecognizer 计算模拟时钟指针的旋转角度