扩展 Marc Gravell 的动态 Linq OrderBy

发布于 2024-11-08 11:16:37 字数 2511 浏览 0 评论 0原文

我发现了 Marc Gravell 的动态 order by 很棒:

Dynamic LINQ OrderBy on IEnumerable

我已经把它了在类 LinqHelper 中。在这个类中,我还创建了两个新类,以便在我的代码中我可以执行此操作:

var q = db.tblJobHeaders;

LinqHelper.OrderByCollection OBys = new LinqHelper.OrderByCollection();
OBys.AddOrderBy("some field", true);
OBys.AddOrderBy("anotherfield", false);
OBys.ExecuteOrderBys(q);

实现此目的的类是:

/// <summary>
/// A collection of order bys
/// </summary>
public class OrderByCollection
{
    private ArrayList Orderings = new ArrayList();

    public OrderByCollection(){ }

    /// <summary>
    /// Add an order by to this collection
    /// </summary>
    public void AddOrderBy(string Field, bool Descending)
    {
        OrderByObj NewObj = new OrderByObj(Descending, Field);
        this.Orderings.Add(NewObj);
    }

    /// <summary>
    /// Executes the order bys
    /// </summary>
    public IOrderedQueryable<T> ExecuteOrderBys<T>(this IOrderedQueryable<T> source)
    {
        int ExecutionIndex = 0;
        foreach (OrderByObj O in this.Orderings)
        {
            if (ExecutionIndex == 0)
            {
                if (O.Descending)
                    source = LinqHelper.OrderByDescending(source, O.Field);
                else
                    source = LinqHelper.OrderBy(source, O.Field);
            }
            else
            {
                if (O.Descending)
                    source = LinqHelper.ThenByDescending(source, O.Field);
                else
                    source = LinqHelper.ThenBy(source, O.Field);
            }
            ExecutionIndex++;
        }
        return (IOrderedQueryable<T>)source;
    }
}

/// <summary>
/// An order by object
/// </summary>
private class OrderByObj
{
    public bool Descending { get; set; }
    public string Field { get; set; }

    public OrderByObj(bool IsDescending, string DatabaseField)
    {
        this.Descending = IsDescending;
        this.Field = DatabaseField;
    }
}

但是,我对将 Linq 变量传递给函数还很陌生(这让我有点困惑)。我目前收到错误:

OBys.ExecuteOrderBys(q);

这给出了错误:

方法的类型参数 'LinqHelper.OrderByCollection.ExecuteOrderBys(System.Linq.IOrderedQueryable)' 无法从用法推断。尝试 指定类型参数 明确地。

如果有人可以帮忙,我对此有点困惑,我是否正确传递了 var q ,然后正确返回它?

I found Marc Gravell's dynamic order by great:

Dynamic LINQ OrderBy on IEnumerable<T>

I've put it in a class, LinqHelper. In this class I also have created two new classes, so that in my code I can do this:

var q = db.tblJobHeaders;

LinqHelper.OrderByCollection OBys = new LinqHelper.OrderByCollection();
OBys.AddOrderBy("some field", true);
OBys.AddOrderBy("anotherfield", false);
OBys.ExecuteOrderBys(q);

The classes to acheive this are:

/// <summary>
/// A collection of order bys
/// </summary>
public class OrderByCollection
{
    private ArrayList Orderings = new ArrayList();

    public OrderByCollection(){ }

    /// <summary>
    /// Add an order by to this collection
    /// </summary>
    public void AddOrderBy(string Field, bool Descending)
    {
        OrderByObj NewObj = new OrderByObj(Descending, Field);
        this.Orderings.Add(NewObj);
    }

    /// <summary>
    /// Executes the order bys
    /// </summary>
    public IOrderedQueryable<T> ExecuteOrderBys<T>(this IOrderedQueryable<T> source)
    {
        int ExecutionIndex = 0;
        foreach (OrderByObj O in this.Orderings)
        {
            if (ExecutionIndex == 0)
            {
                if (O.Descending)
                    source = LinqHelper.OrderByDescending(source, O.Field);
                else
                    source = LinqHelper.OrderBy(source, O.Field);
            }
            else
            {
                if (O.Descending)
                    source = LinqHelper.ThenByDescending(source, O.Field);
                else
                    source = LinqHelper.ThenBy(source, O.Field);
            }
            ExecutionIndex++;
        }
        return (IOrderedQueryable<T>)source;
    }
}

/// <summary>
/// An order by object
/// </summary>
private class OrderByObj
{
    public bool Descending { get; set; }
    public string Field { get; set; }

    public OrderByObj(bool IsDescending, string DatabaseField)
    {
        this.Descending = IsDescending;
        this.Field = DatabaseField;
    }
}

Howver I'm pretty new to passing Linq vars through to functions (the confuses me a bit). I currently get the error on:

OBys.ExecuteOrderBys(q);

Which gives the error:

The type arguments for method
'LinqHelper.OrderByCollection.ExecuteOrderBys(System.Linq.IOrderedQueryable)'
cannot be inferred from the usage. Try
specifying the type arguments
explicitly.

I'm a bit confused about this if anyone could help, am I passing the var q in properly, and then returning it properly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦在夏天 2024-11-15 11:16:37

我敢打赌 q 的类型是 IQueryable 而不是 IOrderedQueryable。只需更改签名就可以了,因为您是从 OrderBy 开始的。

然后,您需要为 ThenBy 提供一个 IOrderedQueryable。您可以直接转换它,因为您确信您在之前对 OrderByThenBy 的调用中获得了 IOrderedQueryable

如果您不喜欢强制转换的想法,则需要进行一些更改:

public IOrderedQueryable<T> ExecuteOrderBys<T>(this IQueryable<T> source)
{
    if(!this.Orderings.Any())
        throw new InvalidOperationException("You need to add orderings");
    IOrderedQueryable<T> ordered;
    if (this.Orderings[0].Descending)
        ordered = LinqHelper.OrderByDescending(source, this.Orderings[0].Field);
    else
        ordered = LinqHelper.OrderBy(source, this.Orderings[0].Field);
    foreach(var ordering in this.Orderings.Skip(1))
    {
        if (ordering.Descending)
            ordered = LinqHelper.ThenByDescending(source, ordering.Field);
        else
            ordered = LinqHelper.ThenBy(source, ordering.Field);
    }
    return ordered;
}

请注意,如果不添加任何排序,您的代码将会严重失败,因为在结尾。您可以将返回类型更改为 IQueryable (这会失去稍后“附加”更多 OrderBy 的能力),或者如果没有排序,则抛出异常,就像我所做的那样。

I bet the type of q is IQueryable<T> and not IOrderedQueryable<T>. Just changing the signature should work, because you start with OrderBy.

Then you will need an IOrderedQueryable<T> for the ThenBys. You can just cast it, because you know for sure that you have an IOrderedQueryable<T> from the previous call to either OrderBy or ThenBy.

If you don't like the idea of the cast, you need some changes:

public IOrderedQueryable<T> ExecuteOrderBys<T>(this IQueryable<T> source)
{
    if(!this.Orderings.Any())
        throw new InvalidOperationException("You need to add orderings");
    IOrderedQueryable<T> ordered;
    if (this.Orderings[0].Descending)
        ordered = LinqHelper.OrderByDescending(source, this.Orderings[0].Field);
    else
        ordered = LinqHelper.OrderBy(source, this.Orderings[0].Field);
    foreach(var ordering in this.Orderings.Skip(1))
    {
        if (ordering.Descending)
            ordered = LinqHelper.ThenByDescending(source, ordering.Field);
        else
            ordered = LinqHelper.ThenBy(source, ordering.Field);
    }
    return ordered;
}

Note your code will fail spectacularly if you don't add any orderings, because of the cast to IOrderedQueryable<T> in the end. You could change the return type to IQueryable<T> (which loses the ability to "attach" more OrderBys later), or throw if there are no orderings, like I did.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文