如何使用反射值创建 OrderBy 语句?

发布于 2024-12-27 05:05:06 字数 479 浏览 1 评论 0原文

我想创建一个方法,通过给定的属性对 IEnumerable 列表进行排序,其中该属性通过字符串 ie 传递到该方法中(请注意,第一个代码示例不起作用,但第二个代码示例起作用,这就是我想要的动态模拟)。

string sortName = "SerialNumber";
IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(what do I stick in here);

这相当于

IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(p => p.SerialNumber);

我怎样才能做到这一点?

I would like to create a method that orders an IEnumerable List by a given property where the property is passed into the method by a string i.e. (Mind you the first code example does not work, but the second does and is what I am trying to emulate dynamically).

string sortName = "SerialNumber";
IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(what do I stick in here);

that would be equivalent to

IEnumerable<PartSummary> partList = FunctionToCreateList();
partOrderedList = partList.OrderBy(p => p.SerialNumber);

How can I accomplish this?

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

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

发布评论

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

评论(2

望笑 2025-01-03 05:05:06

您是说您想将订单传递给您的方法吗?如果是这样,您可以使用以下命令:

Expression<Func<PartSummary, bool>> orderByClause

然后您可以执行以下操作:

partOrderedList = partList.OrderBy(orderByClause);

然后您可以在业务层或任何您希望的位置处理您的订单。

好的,更新:如果您想将列名作为字符串传递,您可以执行如下操作:

为扩展方法创建一个静态类(参考:http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/39028ad2-452e-409f-bc9e-d1b263e921f6/):

static class LinqExtensions
{
    public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortingColumn, bool isAscending)
    {

        if (String.IsNullOrEmpty(sortingColumn))
        {
            return source;
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);

        MemberExpression property = Expression.Property(parameter, sortingColumn);
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        string methodName = isAscending ? "OrderBy" : "OrderByDescending";

        Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
                                            new Type[] { source.ElementType, property.Type },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }
}

然后您可以创建您的方法:

   static IQueryable<PartSummary> FunctionToCreateList()
    {
        IList<PartSummary> list = new List<PartSummary>();
        list.Add(new PartSummary
                     {
                         Id = 1,
                         SerialNumber = "A",
                     });
        list.Add(new PartSummary
                     {
                         Id = 2,
                         SerialNumber = "B",
                     });
        return list.AsQueryable();
    }

然后调用您的方法:

   static void Main(string[] args)
    {
        IQueryable<PartSummary> partOrderedList = FunctionToCreateList();
        PartSummary partSummary = new PartSummary();
        string sortBy = "Id";

        partOrderedList = partOrderedList.OrderBy(sortBy, false);

        foreach (PartSummary summary in partOrderedList)
        {
            Console.WriteLine(summary.Id + ", " + summary.SerialNumber);
        }
        Console.ReadLine();

    }

现在您可以将列名称作为字符串传递并进行排序。

希望这有帮助!

Are you saying you want to pass the order by in to your method? If so, you can use this:

Expression<Func<PartSummary, bool>> orderByClause

Then you can do this:

partOrderedList = partList.OrderBy(orderByClause);

Then you can handle your order by in your business layer or wherever you wish.

Okay, update: If you want to pass in the column name as a string you can do something like as follows:

Create a static class for an extension method (reference: http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/39028ad2-452e-409f-bc9e-d1b263e921f6/):

static class LinqExtensions
{
    public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string sortingColumn, bool isAscending)
    {

        if (String.IsNullOrEmpty(sortingColumn))
        {
            return source;
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, String.Empty);

        MemberExpression property = Expression.Property(parameter, sortingColumn);
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        string methodName = isAscending ? "OrderBy" : "OrderByDescending";

        Expression methodCallExpression = Expression.Call(typeof(Queryable), methodName,
                                            new Type[] { source.ElementType, property.Type },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }
}

Then you can create your method:

   static IQueryable<PartSummary> FunctionToCreateList()
    {
        IList<PartSummary> list = new List<PartSummary>();
        list.Add(new PartSummary
                     {
                         Id = 1,
                         SerialNumber = "A",
                     });
        list.Add(new PartSummary
                     {
                         Id = 2,
                         SerialNumber = "B",
                     });
        return list.AsQueryable();
    }

And then call your method:

   static void Main(string[] args)
    {
        IQueryable<PartSummary> partOrderedList = FunctionToCreateList();
        PartSummary partSummary = new PartSummary();
        string sortBy = "Id";

        partOrderedList = partOrderedList.OrderBy(sortBy, false);

        foreach (PartSummary summary in partOrderedList)
        {
            Console.WriteLine(summary.Id + ", " + summary.SerialNumber);
        }
        Console.ReadLine();

    }

Now you can pass in the column name as a string and sort.

Hope this helps!

甜心 2025-01-03 05:05:06

您还可以避免扩展,只使用编译的表达式树来完成此操作:

    public Func<T, object> ResolveToProperty<T>(String propertyName)
    {
        Type t = typeof(T);
        var paramExpression = Expression.Parameter(t, "element");
        var propertyExpression = Expression.Property(paramExpression, propertyName);
        return Expression.Lambda<Func<T, object>>(propertyExpression, paramExpression).Compile();
    }

    string sortName = "SerialNumber";
    IEnumerable<PartSummary> partList = FunctionToCreateList();
    var partOrderedList = partList.OrderBy(ResolveToProperty<PartSummary>(sortName));

You can also avoid extending and just use a compiled expression tree to accomplish this:

    public Func<T, object> ResolveToProperty<T>(String propertyName)
    {
        Type t = typeof(T);
        var paramExpression = Expression.Parameter(t, "element");
        var propertyExpression = Expression.Property(paramExpression, propertyName);
        return Expression.Lambda<Func<T, object>>(propertyExpression, paramExpression).Compile();
    }

    string sortName = "SerialNumber";
    IEnumerable<PartSummary> partList = FunctionToCreateList();
    var partOrderedList = partList.OrderBy(ResolveToProperty<PartSummary>(sortName));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文