C# 列表上的动态查询选择包含列表

C# 列表上的动态查询选择包含列表,c#,linq,query-builder,dynamicquery,C#,Linq,Query Builder,Dynamicquery,我正在尝试用c#创建一个动态过滤机制 我有一个用户类,它有名字、姓氏、生日等属性,还有UserInformations列表,它是UserInformation对象的列表。 UserInformation对象具有属性Id、名称和值。 和用户列表中的用户列表 我创建了一个UI来使用 它生成类似过滤器的 { "condition": "AND", "rules": [ { "id": "name", "field": "name", "type": "

我正在尝试用c#创建一个动态过滤机制

我有一个用户类,它有名字、姓氏、生日等属性,还有UserInformations列表,它是UserInformation对象的列表。 UserInformation对象具有属性Id、名称和值。 和用户列表中的用户列表

我创建了一个UI来使用

它生成类似过滤器的

{
  "condition": "AND",
  "rules": [
    {
     "id": "name",
      "field": "name",
      "type": "string",
      "input": "text",
      "operator": "equal",
      "value": "huseyin"
    },
    {
      "condition": "OR",
      "rules": [
        {
          "id": "surname",
          "field": "surname",
          "type": "string",
          "input": "text",
          "operator": "equal",
          "value": "34"
        },
        {
          "id": "ix_2_Weight",
          "field": "ix_2_Weight",
          "type": "integer",
          "input": "select",
          "operator": "equal",
          "value": 50
        }
      ]
    }
  ],
  "valid": true
}
我对带有User属性的过滤器没有问题。但是,我正在尝试过滤UserInformations数组中的信息。 若字段名以ix开头并获取用户信息的id,则我将拆分字段名。但我找不到如何比较它的价值。 如果它是一个静态linq,它应该是

users.Where(u=>u.Informations.FirstOrDefault(i=>i.id==2/*id of information in filter*/)?.Value=="something"))
使用下面的代码调用过滤器

 private async Task<List<User>> FilterUsers(FilterRule rule, List<UserFilterDto> users = null)
        {
            List<User> list = users ?? await GetUsersForFilter();

            var tempList = list.BuildQuery(rule).ToList();
            return tempList;

        }
专用异步任务筛选器用户(筛选器规则,列表用户=null)
{
List List=用户??等待GetUsersForFilter();
var templast=list.BuildQuery(rule.ToList();
返回圣殿骑士;
}
动态查询部分如下


公共静态IQueryable构建查询(此IQueryable可查询,FilterRule FilterRule,out string parsedQuery,bool useIndexedProperty=false,string indexedPropertyName=null)
{
如果(filterRule==null)
{
parsedQuery=“”;
返回可查询;
}
var pe=Expression.Parameter(typeof(userdetaileddo),“item”);
var expressionTree=BuildExpressionTree(pe、filterRule、useIndexedProperty、indexedPropertyName);
if(expressionTree==null)
{
parsedQuery=“”;
返回可查询;
}
parsedQuery=expressionTree.ToString();
var whereCallExpression=Expression.Call(
类型(可查询),
“哪里”,
新[]{queryable.ElementType},
可查询的表达式,
Lambda(expressionTree,pe));
var filteredResults=queryable.Provider.CreateQuery(whereCallExpression);
返回筛选结果;
}
公共静态IQueryable构建查询(此IQueryable可查询,FilterRule FilterRule,out string parsedQuery,bool useIndexedProperty=false,string indexedPropertyName=null)
{
如果(filterRule==null)
{
parsedQuery=“”;
返回可查询;
}
var pe=Expression.Parameter(typeof(userdetaileddo),“item”);
var expressionTree=BuildExpressionTree(pe、filterRule、useIndexedProperty、indexedPropertyName);
if(expressionTree==null)
{
parsedQuery=“”;
返回可查询;
}
parsedQuery=expressionTree.ToString();
var whereCallExpression=Expression.Call(
类型(可查询),
“哪里”,
新[]{queryable.ElementType},
可查询的表达式,
Lambda(expressionTree,pe));
var filteredResults=queryable.Provider.CreateQuery(whereCallExpression);
返回筛选结果;
}
私有静态表达式BuildExpressionTree(ParameterExpression pe,FilterRule规则,bool useIndexedProperty=false,string indexedPropertyName=null)
{
if(rule.Rules!=null&&rule.Rules.Any())
{
变量表达式=
选择(childRule=>BuildExpressionTree(pe、childRule、useIndexedProperty、indexedPropertyName))
.Where(表达式=>表达式!=null)
.ToList();
var expressionTree=expressions.First();
var计数器=1;
while(计数器u => u.Informations.FirstOrDefault(i => i.id == 2)?.Value == "something"))
u => u.Informations.Any(i => i.id == 2 && i.Value == "something"))
private static Expression BuildCondition(FilterRule rule, Expression propertyExp)
{
    Type type;

    switch (rule.Type)
    {
        case "integer":
            type = typeof(int);
            break;
        case "long":
            type = typeof(long);
            break;
        case "double":
            type = typeof(double);
            break;
        case "string":
            type = typeof(string);
            break;
        case "date":
        case "datetime":
            type = typeof(DateTime);
            break;
        case "boolean":
            type = typeof(bool);
            break;
        default:
            throw new Exception($"Unexpected data type {rule.Type}");
    }

    Expression expression;

    switch (rule.Operator.ToLower())
    {
        case "in":
            expression = In(type, rule.Value, propertyExp);
            break;
        case "not_in":
            expression = NotIn(type, rule.Value, propertyExp);
            break;
        case "equal":
            expression = Equals(type, rule.Value, propertyExp);
            break;
        case "not_equal":
            expression = NotEquals(type, rule.Value, propertyExp);
            break;
        case "between":
            expression = Between(type, rule.Value, propertyExp);
            break;
        case "not_between":
            expression = NotBetween(type, rule.Value, propertyExp);
            break;
        case "less":
            expression = LessThan(type, rule.Value, propertyExp);
            break;
        case "less_or_equal":
            expression = LessThanOrEqual(type, rule.Value, propertyExp);
            break;
        case "greater":
            expression = GreaterThan(type, rule.Value, propertyExp);
            break;
        case "greater_or_equal":
            expression = GreaterThanOrEqual(type, rule.Value, propertyExp);
            break;
        case "begins_with":
            expression = BeginsWith(type, rule.Value, propertyExp);
            break;
        case "not_begins_with":
            expression = NotBeginsWith(type, rule.Value, propertyExp);
            break;
        case "contains":
            expression = Contains(type, rule.Value, propertyExp);
            break;
        case "not_contains":
            expression = NotContains(type, rule.Value, propertyExp);
            break;
        case "ends_with":
            expression = EndsWith(type, rule.Value, propertyExp);
            break;
        case "not_ends_with":
            expression = NotEndsWith(type, rule.Value, propertyExp);
            break;
        case "is_empty":
            expression = IsEmpty(propertyExp);
            break;
        case "is_not_empty":
            expression = IsNotEmpty(propertyExp);
            break;
        case "is_null":
            expression = IsNull(propertyExp);
            break;
        case "is_not_null":
            expression = IsNotNull(propertyExp);
            break;
        default:
            throw new Exception($"Unknown expression operator: {rule.Operator}");
    }

    return expression;
}
if (rule.Field.StartsWith("ix_"))
{
    var tokens = rule.Field.Split("_");
    var infoParameter = Expression.Parameter(typeof(UserInformation), "i");
    var infoCondition = Expression.AndAlso(
        Expression.Equal(
            Expression.Property(infoParameter, nameof(UserInformation.Id)),
            Expression.Constant(long.Parse(tokens[1]))),
        BuildCondition(rule, Expression.Property(infoParameter, tokens[2])));
    return Expression.Call(
        typeof(Enumerable), nameof(Enumerable.Any), new[] { infoParameter.Type },
        Expression.Property(pe, nameof(User.Informations)),
        Expression.Lambda(infoCondition, infoParameter));
}