Сортировка списка с использованием отражения для передачи имени члена по строке - PullRequest
0 голосов
/ 13 июня 2018

У меня есть классы и mini и их List<T>.

List<mini> result;

public class mini
{
    public long SN;
    public int PlayTime;
    public string Date;
    public int Score;
}

//The value is the Name of SN, PlayTime, Date, Score
string sortColumn;      
string sortColumnDir;  //asc, desc value

Вызывающая сторона может указать имя члена для сортировки, и я пытаюсь отсортировать значение результата:

if("SN" == sortColumn)
    var sortresult = result.OrderBy(c => c.SN).ToList<miniCompletion>();
else if("PlayTime" == Date)
    var sortresult = result.OrderBy(c => c.PlayTime).ToList<miniCompletion>();
else if("PlayTime" == sortColumn)
    var sortresult = result.OrderBy(c => c.PlayTime).ToList<miniCompletion>();
else if("Score" == sortColumn)
    var sortresult = result.OrderBy(c => c.Score).ToList<miniCompletion>();

Но этот код слишком неэффективен, потому что он включает в себя много копий, почти дублирующих код.А для сортировки по убыванию код удваивается в размере.

Поэтому я попытался:

var sortresult = result.OrderBy(c => c.GetType().GetMember(sortColumn)[0].Name).ToList();

Но сортировка не удалась.

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

Измените это:

if("SN" == sortColumn) var sortresult = result.OrderBy(c => c.SN).ToList<miniCompletion>(); else if("PlayTime" == Date) var sortresult = result.OrderBy(c => c.PlayTime).ToList<miniCompletion>(); else if("PlayTime" == sortColumn) var sortresult = result.OrderBy(c => c.PlayTime).ToList<miniCompletion>(); else if("Score" == sortColumn) var sortresult = result.OrderBy(c => c.Score).ToList<miniCompletion>();

С перечислениями для asc, desc и sortColumn, например:

If(SortComun.SN == sortColumn)

Сравнение Int быстрее, а перечисления чище.Кроме того, вы можете попробовать result.AsParallel (). OrderBy (), если у вас слишком много регистров.

Что касается вашего второго подхода, попробуйте:

var sortResult = result.OrderBy(c => c.GetType().GetProperty(sortColumn).GetValue(c)).ToList();

Вы можете проверить, какой подход вам подходитлучше.Если рефлексия является самым общим ответом, другой может быть быстрее в интенсивной среде.

Если вы тестируете и делитесь своими результатами, результат может быть потрясающим.

0 голосов
/ 13 июня 2018

Вы можете динамически строить свою лямбда-сортировку с помощью выражений linq.Попробуйте этот код:

var parameter = Expression.Parameter(typeof(mini), "c");
var member = Expression.PropertyOrField(parameter, sortColumn);
var cast = Expression.Convert(member, typeof(IComparable));
var lambda = Expression.Lambda<Func<mini, IComparable>>(cast, parameter);

сейчас lambda является выражением типа c => (IComparable)c.Date и может быть скомпилировано в Func<mini, IComparable>:

var func = lambda.Compile();

В этот момент вы можете отсортировать result:

var sortedResult = sortColumnDir == "ASC"
    ? result.OrderBy(func)
    : result.OrderByDescending(func);

Демонстрацию можно найти здесь

Обратите внимание, что этот код работает, поскольку все поля в mini реализуют интерфейс IComparable

0 голосов
/ 13 июня 2018

Сортировка не удалась, потому что вы сортируете по свойству name , а не по его значению.Имя, конечно, одинаково для всех предметов.

Вам необходимо получить значение .Используйте GetField(...).GetValue(c).Если вы не можете использовать GetField() (или вы даже предпочитаете использовать свойства, а не поля, поэтому GetProperty()), см. Как получить значение MemberInfo? .

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