通用的Linq OrderBy函数存在问题

5

我在一篇帖子中看到了以下函数,它允许使用通用表达式对数据进行排序:

public static IOrderedQueryable<T> OrderBy<T, TKey>(
  this IQueryable<T> source, Expression<Func<T, TKey>> func, bool isDescending) {
  return isDescending ? source.OrderByDescending(func) : source.OrderBy(func);
}

当我尝试使用此函数时,出现错误提示:“找不到类型或命名空间名称“TKey”(是否缺少using指令或程序集引用?)”。我在这里做了一些蠢事,但我想不出来。
编辑:
经过更多的研究,我认为我的问题在于构建传递给它的Expression。是否可能构建包含不同类型的表达式?假设我的数据集有一个字符串、一个整数和一个布尔值,我想使用上面的通用函数按任何项排序。我该怎么做呢?
我现在已经解决了这个问题:
if (IsString)
{
   Expression<Func<T, string>> expString = ...;
   // call orderBy with expString
}
else if (IsInt)
{
   Expression<Func<T, int>> expInt;
   // call orderBy w/ expInt
}
:

我想要类似这样的东西:

Expression<Func<T, {something generic!}>> exp;
if (IsString)
    exp = ...;
else if (IsInt)
    exp = ...;
:
// call orderBy with exp

这看起来不错。你是怎么使用这个方法的?你把它添加到了一个静态类中吗? - BFree
5个回答

4

一个快速的观察:你并不真正需要使用lambda表达式(Expression<Func<T,TKey>>),一个简单的委托(Func<T,TKey>)就可以了。

话虽如此,我认为你可能在寻找的答案是这样的:

Func<T,IComparable> func = null;
if (IsString)
    func = (T a) => a.SomeStringValue;
else if (IsInt)
    func = (T a) => a.SomeIntValue;
// call orderBy with exp

这似乎是我在寻找的东西。然而,我稍微尝试了一下,但无法编译它。当我尝试将func传递到OrderBy函数时,编译器会抱怨。如果您的方法可以工作,那么它会更清晰一些,但不幸的是我现在无法再投入更多时间。 - ejwipp
1
当您有时间的时候,请告诉我您看到的编译器错误是什么。 - jpbochi
我终于回到了这个问题。我认为问题在于我的自定义orderBy函数中,我调用了ThenBy,它不接受Func参数-而需要lambda表达式。 - ejwipp
你可以创建一个接受 Func 参数的 ThenBy 重载方法。当你需要以某种方式分析表达式时,应该使用 Lambda 表达式。如果你只需要执行表达式,则应该使用委托。 - jpbochi

2

我的目标是消除很多重复的代码。除了处理升序/降序之外,我的“OrderBy”函数还处理一些其他常见逻辑。假设在原始帖子中有函数定义,可以简单地执行以下操作:

if ( {need to sort by integer})
    query = OrderBy(objectT, a => a.myIntegerField, asc);
else if ( {need to sort by string})
    query = OrderBy(objectT, a=> a.myStringField, asc);
:

1

表达式只能有一种类型;我在这里的首选答案可能是:

IQueryable<T> query = ...
if({case 1}) {
    query = query.OrderBy(x=>x.SomeValue);
} else if({case 2}) {
    query = query.OrderBy(x=>x.SomeOtherValue);
} ...

然而,如果你想要做一些更加灵活的事情,你可能需要进入自定义Expression编写;类似于这样的内容


这就是我最初的代码,但由于我有许多字段需要处理升序/降序排序,所以最终出现了大量“重复”的代码。我发布的答案似乎运行良好。 - ejwipp

0

0

看一下这个答案

我的通用处理程序用于排序:

  • "dgvProcessList" 是我的 dataGridView
  • "Process" 是我绑定到它上面的对象
  • "e" 是我的 DataGridViewCellMouseEventArgs

                PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();
            if (isSortedASC == true)
                dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderByDescending(x => column.GetValue(x, null)).ToList();
            else
                dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderBy(x => column.GetValue(x, null)).ToList();
    
            isSortedASC = !isSortedASC;
            dgvProcessList.ClearSelection();
    

干杯


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接