LinqExpression 嵌套属性,与字符串进行比较

本文关键字:比较 字符串 嵌套 属性 LinqExpression | 更新日期: 2023-09-27 18:35:09

我正在努力实现一种通用模式,以便能够过滤 where 子句。 基本用例是我们的 API 接受一个名为 ?filterBy:AddressState:VA 的查询参数。

我正在尝试创建能够将子句一般附加到IQueryable的东西。 基本上每个 API 都需要创建一个 key/Expressions字典,该字典将查找属性以比较filterBy的右侧,例如 VA.. 这是我到目前为止所拥有的,但它目前因错误而崩溃

"二元运算符 Equal 未为类型'System.Func'2[Framework.Models.User,System.String]' 和 'System.String' 定义。

示例字典:

public Dictionary<string, Expression<Func<User, Object>>> FILTER_BY = new Dictionary<string, Expression<Func<User, Object>>>()  
{
    { "addressstate", (x) => x.Address.State},   
};

调用使用扩展方法:

baseQ = baseQ.FilterBy(filterBy, FILTER_BY);

扩展方法:

 public static string GetPropertySymbol<T, TResult>(this Expression<Func<T, TResult>> expression)
 {
      return String.Join(".",
          ((MemberExpression)expression.Body).GetMembersOnPath()
             .Select(m => m.Member.Name)
             .Reverse());
 }

将嵌套选择转换为强选择的帮助程序方法

 static Expression CreateExpression(Type type, string propertyName)
 {
   var param = Expression.Parameter(type, "x");
   Expression body = param;
   foreach (var member in propertyName.Split('.'))
   {
      body = Expression.PropertyOrField(body, member);
   }
   return Expression.Lambda(body, param);
 }

实用程序功能已损坏。

  public static IQueryable<T> FilterBy<T, TProperty>(this IQueryable<T> query, string filterBy, Dictionary<string, Expression<Func<T, TProperty>>> filterExpressions)
 {
   if (!string.IsNullOrEmpty(filterBy))
   {
     //parse on ':' throw argument if there is not two.
     var split = filterBy.Split(':');
     var key = split[0];
     var right = string.Join("", split.Skip(1));
     var expression  =filterExpressions.FirstOrDefault(x=>x.Key == key.ToLower());
     if (expression.Key != null)
     {
        var parameterItem = Expression.Parameter(typeof(T), "item");
        var rightExp = Expression.Constant(right);
        var left = CreateExpression(typeof(T),expression.Value.GetPropertySymbol()); 
        var lambda = Expression.Lambda<Func<T, bool>>(
                Expression.Equal(
                    left,
                     rightExp
                 ),
                 parameterItem
         );
        return query.Where(lambda);
     }
  }
  return query;
} 

一旦我得到了一个基本的字符串比较工作,我实际上可能会看到关于做其他类型的常量字符串、整数、日期时间的信息。 但我可以用字符串短期获得。

如果您有任何其他问题,请告诉我。 我尝试了一种不同的方法,我尝试包装基本上称为 Invoke 的现有函数,然后生成一个新函数,但它导致实体框架抛出关于 .不支持调用。

LinqExpression 嵌套属性,与字符串进行比较

此方法

static Expression CreateExpression(Type type, string propertyName)

创建单独的参数。您需要修改它以接收参数作为参数并仅返回正文(而不是 lambda),所以这里

var left = CreateExpression(typeof(T),expression.Value.GetPropertySymbol()); 

你可以这样称呼它

var left = CreateExpression(parameterItem,expression.Value.GetPropertySymbol()); 

修改后的函数可以是这样的

static Expression CreateExpression(ParameterExpression param, string propertyName)
{
    Expression body = param;
    foreach (var member in propertyName.Split('.'))
    {
        body = Expression.PropertyOrField(body, member);
    }
    return body;
}

或简单

static Expression CreateExpression(Expression target, string memberPath)
{
    return memberPath.Split('.').Aggregate(target, Expression.PropertyOrField);
}