универсальный метод сортировки по строковому полю - PullRequest
2 голосов
/ 28 февраля 2011

У меня есть ситуация здесь, и я не уверен, что лучший способ продолжить это ...

Мой код переднего плана (ASP.NET) постоянно получает списки бизнес-объектов для заполнения пользовательского интерфейсакомпоненты.Недавно я реализовал естественную сортировку, которую хочу использовать для всех типов этих списков.(в настоящее время он просто сортирует списки строк). В зависимости от типа бизнес-объекта, мне нужно отсортировать по другому имени поля.Поле всегда содержит строку.Я знаю имя поля во время компиляции.Бизнес-объекты не имеют общего родителя, кроме Object.

Я хотел бы иметь один метод, который может сделать это для Enumerable любого типа.Я не могу изменить код для базовых бизнес-объектов.Как бы вы пошли об этом?

Ответы [ 7 ]

5 голосов
/ 28 февраля 2011

Что-то вроде заказа Линка ?

Вы должны реализовать естественную сортировку в IComparer, но тогда вы просто используете:

Items.OrderBy(i => i.SomeStringField, NaturalSorter);
1 голос
/ 28 февраля 2011

Вы можете использовать анонимную функцию для получения правильной строки. Это означает, что вы должны передать как список объектов, так и лямбда-выражение или делегат анонимного метода, чтобы извлечь строку в ваш метод сортировки.

sort(listOfFoos, o => ((Foo) o).name());

В последнее время я сам не слишком много использовал C #, так что другие, вероятно, могут кричать мне, если это не сработает.

1 голос
/ 28 февраля 2011

Поскольку у вас нет общего типа, к которому вы можете обращаться к свойствам строго типизированным способом, вы не можете использовать OrderBy напрямую, как это предлагается в других ответах.

Вам нужно будет использовать отражение, чтобы получить ссылку на объект свойства и попросить его извлечь свое значение для каждого элемента в последовательности:

public static IOrderedEnumerable<TSource> OrderByProperty<TSource>(
    this IEnumerable<TSource> source,
    string propertyName)
{
    var property = typeof(TSource).GetProperty(propertyName);

    return source.OrderBy(item => (string) property.GetValue(item, null));
}

Конечно, если во время выполнения вы знаете поля и точного типа списка для сортировки, вы должны вместо этого использовать строго типизированную перегрузку OrderBy. Это предложение только в том случае, если вы не знаете, какие элементы в списке сортировать (т. Е. IEnumerable<object>).

1 голос
/ 28 февраля 2011

Вам необходимо создать ключевой селектор. Взгляните на Enumerable.OrderBy . Его второй параметр - это ключевой селектор. Реализуйте это, чтобы учесть тип бизнес-объекта, например ::1003*

delegate (object o)
{
  if (o is BizType1) return ((BizType1)o).Property1;
  else if (o is BizType2) return ((BizType2)o).Property2;
}
1 голос
/ 28 февраля 2011

Вы можете использовать отражение:

private string GetStringValue(object input, string propertyName)
{
    PropertyInfo pi = typeof(input).GetProperty(propertyName);
    return pi.GetGetMethod().Invoke(input) as String;
}

Это позволит получить значение заданного свойства для вашего объекта, и затем вы можете применить сортировку на основе этого.

0 голосов
/ 28 февраля 2011
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //lets say this is the list that you have you mah have more fields
            List<Person> people = new List<Person>();

            people.Add(new Person(25, "Jhon"));
            people.Add(new Person(22, "Antonio"));
            people.Add(new Person(21, "Waid"));
            people.Add(new Person(21, "Chris"));
            people.Add(new Person(26, "Lacy"));
            people.Add(new Person(21, "Albert"));
            people.Add(new Person(45, "Tom"));
            people.Add(new Person(65, "Bob"));



            var query = from a in people   // crate a query from your list in this case the list is people
                        where a.age > 18 && a.age < 50  // select just people that has an age greater than 0 and less than 100
                                                        // maybe you want to filter some results if you dont then delete this line.
                        orderby a.name                  // order the results by their name
                        select a.name;                  // then select just the name. if you type select just a then query will 
                                                        // contain a list of ages too.

            // loop though the results to see if they were ordered
            foreach (string name in query)
            {
                Console.WriteLine(name);
            }            
            Console.Read();

        }
    }

    // I created this class because I dont know what your list contains I know it has a string therefore I added a string
    // you may add more properties and it will still work...
    class Person
    {
        public int age;
        public string name;

        public Person(int a, string n)
        {
            age = a;
            name = n;
        }
    }
}
0 голосов
/ 28 февраля 2011

Для каждого бизнес-объекта реализуйте интерфейс IComparable<T>.
Затем используйте метод LINQ OrderBy, который автоматически использует ваш метод для сортировки.

Если вы не можете или не хотите включать логику сортировки в классы бизнес-объектов, вы также можете реализовать IComparer<T> и передать ее в OrderBy перегрузку .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...