【问题标题】:C# Sort array of objects by property name exists in the objectC#按属性名称对对象数组进行排序,对象中存在
【发布时间】:2015-10-27 13:24:38
【问题描述】:

以下代码,按对象中存在的任何属性名称(作为字符串)对任何对象数组进行排序。

排序数组也是使用排序方向“asc”或“desc”完成的。

这是我要申请的目标。

    using System.Linq.Dynamic;

    /// <summary>
    /// This method sorts any array of objects.
    /// </summary>
    /// <param name="dataSource">Array of objects</param>
    /// <param name="propertyName">property name to sort with</param>
    /// <param name="sortDirection">"ASC" or "DESC"</param>
    /// <returns></returns>
    private object[] SortArrayOfObjects(object[] dataSource, string propertyName, string sortDirection)
    {
        string sortExpression = string.Format("{0} {1}", propertyName, sortDirection);
        // sortExpression will be something like "FirstName DESC".

        // OrderBy method takes expression as string like "FirstName DESC".
        // OrderBy method exists in "System.Linq.Dynamic" dll.
        // Download it from www.nuget.org/packages/System.Linq.Dynamic/
        object[] arrSortedObjects = dataSource.OrderBy(sortExpression).ToArray();

        return arrSortedObjects;
    }

【问题讨论】:

  • 在那之后您将无法使用 LINQ - 而且这样做没有任何意义,因为您实际上已经丢失了类型信息(您无法编写,例如:@ 987654323@ 因为 1. 您不再知道 newArrEmpInfo 是否是 IEnumerable,以及 2. 您不知道集合中的任何对象都有 Id 属性 - 或者它甚至是 int) .您能否提供有关您要完成的工作的更多信息? (你的目标;不是实施)
  • Convert.ChangeType 就像您的类型支持 IConvertible 和更多的值类型(结构,仍然不适用于所有人)一样好。可能你应该看看Dapper dot net 类型转换或者只是等待我会尝试同时写一些东西。
  • 变量的类型是编译时的概念。您的声明 objType newArrEmpInfo 和强制转换一样零意义,因为 dataSource 引用的对象 已经是 它是什么类型。实际上,调用Convert.ChangeType() 没有执行nothing,因为dataSource 已经是您要求方法将其更改为的运行时类型。无论您实际尝试做什么,您都需要更好地解释,以便我们能够真正理解您的问题。你在这里问的问题根本没有任何意义。

标签: c# linq sorting dynamic


【解决方案1】:

你可以做你想做的事,让方法泛型接受来自调用方法的类型,然后使用类型参数 T 将 dataSource 强制转换为。

private object[] SortArrayOfObjects<T>(object[] dataSource, string propertyName, string sortDirection)
    {
        string sortExpression = string.Format("{0} {1}", propertyName, sortDirection);
        // sortExpression will be something like "FirstName DESC".

        // OrderBy method takes expression as string like "FirstName DESC".
        // OrderBy method exists in "System.Linq.Dynamic" dll.
        // Download it from www.nuget.org/packages/System.Linq.Dynamic/
        object[] arrSortedObjects = dataSource.Cast<T>().OrderBy(sortExpression).Cast<object>().ToArray();

        return arrSortedObjects;
    }
}

// Use it like:       | You pass the type, so no need for hardcoding it, and it should work for all types.
SortArrayOfObjects<EmployeeInfo>(object[] dataSource, string propertyName, string sortDirection);

这是一个完整的演示:

把这个放到一个DLL输出的项目中: 使用系统; 使用 System.Collections.Generic; 使用 System.Text; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Linq.Dynamic;

namespace GenericMethod
{
    public class GenericMethodClass
    {
        public T[] SortArrayOfObjects<T>(object[] dataSource, string propertyName, string sortDirection)
        {
            string sortExpression = string.Format("{0} {1}", propertyName, sortDirection);
            // sortExpression will be something like "FirstName DESC".

            // OrderBy method takes expression as string like "FirstName DESC".
            // OrderBy method exists in "System.Linq.Dynamic" dll.
            // Download it from www.nuget.org/packages/System.Linq.Dynamic/
            T[] arrSortedObjects = dataSource.Cast<T>().OrderBy(sortExpression).ToArray();

            return arrSortedObjects;
        }
    }
}

将其放入控制台应用程序项目中,并确保引用包含上述代码的库: 使用系统; 使用 System.Collections.Generic; 使用 System.Text; 使用通用方法; 使用 System.Linq;

namespace GenericMethodApp
{
    public class Program
    {
        static void Main(string[] args)
        {
            var employees = new object[]
            {
                new EmployeeInfo { FirstName = "Mohammed" },
                new EmployeeInfo { FirstName = "Ghasan" }
            };

            var students = new object[]
            {
                new Student { StudentName = "Mike" },
                new Student { StudentName = "Harris" }
            };

            var genericMethodClass = new GenericMethodClass();

            // Note that the generic method returns the array of the specific type
            // thanks to the T type parameter.
            EmployeeInfo[] returnedEmployees = genericMethodClass.SortArrayOfObjects<EmployeeInfo>(employees, "FirstName", "ASC");
            Student[] returnedStudents = genericMethodClass.SortArrayOfObjects<Student>(students, "StudentName", "ASC");

            foreach (var employee in returnedEmployees)
                Console.WriteLine(employee.FirstName);

            Console.WriteLine();

            foreach (var Student in returnedStudents)
                Console.WriteLine(Student.StudentName);

            Console.ReadKey();
        }
    }

    public class EmployeeInfo
    {
        public string FirstName { get; set; }
    }

    public class Student
    {
        public string StudentName { get; set; }
    }
}

你已经完成了。

确保在 DLL 中引用 System.Linq.Dynamic。

【讨论】:

  • 方法 'SortArrayOfObjects' 将放在一个 dll 中,我想从 dll 本身调用它。 EmployeeInfo 在 UI 层中声明。我怎么称呼它?
  • @MohammedOsman 没问题。在 dll 中,您将放置通用 SortArrayOfObjects&lt;T&gt;(不引用 EmployeeInfo),当从 UI 调用它时(因此您可以访问 EmployeeInfo),您可以像这样调用它SortArrayOfObjects&lt;EmployeeInfo&gt;。在另一个项目中,您可以使用SortArrayOfObjects&lt;DepartmentInfo&gt;。该方法是通用的,只要您可以访问该类型,就没有问题。它适用于所有人。
  • @Ghsan 我想在类GenericMethodClass 中创建一个名为public void ProcessArray(object[] dataSource, string propertyName, string sortDirection) 的函数,该函数调用函数SortArrayOfObjects&lt;T&gt;(object[] dataSource, string propertyName, string sortDirection) 我该怎么做?这是从 dll 而不是 UI 层调用排序方法的目标。
  • @MohammedOsman 你不能做你想做的事。您必须告诉编译器您要转换为的类型。我想了解您为什么要实现这一点,直接在 UI 内调用 SortArrayOfObjects&lt;T&gt;(object[] dataSource, string propertyName, string sortDirection) 有什么问题?
  • @Ghsan 我正在做一个自定义控件CustomGridView : GridView,它将 object[] of 作为数据源。我想在我的自定义 GridView 中处理网格的排序。有人说我可以通过反射进行排序。但是当我知道System.Linq.Dynamic时,我喜欢使用它。
猜你喜欢
  • 2010-11-24
  • 2011-09-06
  • 2021-09-05
  • 1970-01-01
  • 2016-11-25
  • 2010-10-27
相关资源
最近更新 更多