动态Orderby函数

本文关键字:函数 Orderby 动态 | 更新日期: 2023-09-27 18:21:21

在我的"Invoice"类中,它有20多个字段,我需要支持对所有字段进行排序。

我有一个接受属性字符串的方法(例如"AmountDue")。现在我需要OrderBy AmoundDue字段。

我的具体要求是,传递一个属性名称字符串值,我想返回一个类似的函数

Func<Invoice, decimal> keySelector = a=> a.AmountDue

其中整个表达式是动态构建的。

其中我可以使用keySelector对进行排序

_api.Invoices.Find().Where(c => c.Contact.Id == contactId).OrderBy(keySelector).ToList();

到目前为止,我能够用字符串值来识别类型。需要一些帮助才能返回函数。

  public static Type VariableType(string prop)
    {
        Type type = typeof(TResource);
        PropertyInfo pi = type.GetProperty(prop, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
        type = pi.PropertyType;
        return type;
    }

在我提出这个问题之前,我提到了这个帖子。输入考虑的两个问题相同,但产出不同。我尝试使用该解决方案并四处玩耍,但无法解决我的具体问题。在我的情况下,我正在调用第三方API(Xeroapi),我想专门构建这个输出。

动态Orderby函数

排序时,必须返回属性值,而不是类型自身属性

  String propertyName = "AmountDue";
  var result = _context
    .Invoices
    .Find()
    .Where(c => c.Contact.Id == contactId)
    .OrderBy(item => typeof(Invoice).GetProperty(
         propertyName, 
         BindingFlags.Public | BindingFlags.Instance)
       .GetValue(item))
    .ToList();

您可以将对象传递给反射函数并返回适当的属性,如下所示:

.OrderBy(o => keySelector(o, propertyName))
public static Type VariableType(object o, string prop)
{
    Type type = typeof(TResource);
    PropertyInfo pi = type.GetProperty(prop, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
    return pi.GetValue(o);
}

但我认为这在IQueryable上不起作用,因为它无法将函数转换为SQL。因此,您必须首先执行查询(例如使用ToList()

_context.Invoices.Find().Where(c => c.Contact.Id == contactId).ToList().OrderBy(o => keySelector(o, propertyName)).ToList();

Grundy在评论中建议使用dynamic LINQ可能是更好的解决方案。

您可能还希望能够在排序方向(升序、降序)之间切换。这会给你带来另一个问题。通过一些小的改变,您应该能够根据这个答案调整您的解决方案。

使用方法非常简单,只需在集合上调用Extension方法OrderBy<T>即可。这也是您要查找的代码块所在的位置。

您可以在字典中进行简单的查找,而不是进行反射。

static readonly Dictionary<string, Func<Invoice, decimal>> keySelectors = ...;

在启动时(或使用Lazy),您初始化所有密钥选择器:

keySelectors.Add("AmountDue", a=> a.AmountDue);
// add all 20 options here

现在,每次你需要一个,它只是一个快速的字典查找。

优点:

  • 将用于连接UI和业务逻辑的字符串与字段名解耦,从而可以安全地重构它们
  • 团队中的其他开发人员很容易理解和维护