【发布时间】:2018-02-13 20:55:12
【问题描述】:
我正在尝试找出一种方法来构造我的数据,以便它是模型可绑定的。我的问题是我必须创建一个可以表示数据中的多个表达式的查询过滤器。
例如:
x => (x.someProperty == true && x.someOtherProperty == false) || x.UserId == 2
x => (x.someProperty && x.anotherProperty) || (x.userId == 3 && x.userIsActive)
我已经创建了这个结构,它代表了所有表达式,我的问题是我怎样才能使它成为可绑定的属性模型
public enum FilterCondition
{
Equals,
}
public enum ExpressionCombine
{
And = 0,
Or
}
public interface IFilterResolver<T>
{
Expression<Func<T, bool>> ResolveExpression();
}
public class QueryTreeNode<T> : IFilterResolver<T>
{
public string PropertyName { get; set; }
public FilterCondition FilterCondition { get; set; }
public string Value { get; set; }
public bool isNegated { get; set; }
public Expression<Func<T, bool>> ResolveExpression()
{
return this.BuildSimpleFilter();
}
}
//TODO: rename this class
public class QueryTreeBranch<T> : IFilterResolver<T>
{
public QueryTreeBranch(IFilterResolver<T> left, IFilterResolver<T> right, ExpressionCombine combinor)
{
this.Left = left;
this.Right = right;
this.Combinor = combinor;
}
public IFilterResolver<T> Left { get; set; }
public IFilterResolver<T> Right { get; set; }
public ExpressionCombine Combinor { get; set; }
public Expression<Func<T, bool>> ResolveExpression()
{
var leftExpression = Left.ResolveExpression();
var rightExpression = Right.ResolveExpression();
return leftExpression.Combine(rightExpression, Combinor);
}
}
我的左右成员只需要能够解析为 IResolvable,但模型绑定器只绑定到具体类型。我知道我可以编写自定义模型绑定器,但我更希望只有一个可以工作的结构。
我知道我可以将 json 作为解决方案传递,但作为要求我不能
有没有一种方法可以改进这个结构,使其在模型可绑定的同时仍然可以表示所有简单的表达式?还是有一种简单的方法可以应用此结构以便它与模型绑定器一起使用?
编辑 万一有人想知道,我的表达式构建器有一个它过滤的成员表达式白名单。动态过滤工作我只是在寻找一种自然绑定此结构的方法,以便我的 Controller 可以接收 QueryTreeBranch 或接收准确表示相同数据的结构。
public class FilterController
{
[HttpGet]
[ReadRoute("")]
public Entity[] GetList(QueryTreeBranch<Entity> queryRoot)
{
//queryRoot no bind :/
}
}
目前 IFilterResolver 有 2 个实现,需要根据传递的数据动态选择
我正在寻找最接近开箱即用 WebApi / MVC 框架的解决方案。最好不需要我将输入调整到另一个结构以生成我的表达式
【问题讨论】:
-
你有一套固定的表达式,查询过滤器,可以使用还是完全动态的?
-
你能提供一个不可行的例子来说明你想要这样做吗?
-
@aaronR 我正在使用成员表达式将我的访问权限列入白名单,我将在一秒钟内更新问题
-
@Nkosi 最终这将是一个轻量级的 OData,但我允许客户端传入简单的过滤器并将我的访问列入白名单,因此您可以动态过滤实体。 IE { propertyName: "Id", filterCondition: "equals", value: "3" }
-
@Nkosi 我需要支持简单的二进制表达式等
标签: c# expression filtering dynamic-programming