Как я могу вернуть IOrderedEnumerable из коллекции на основе "свойства" OrderBy
class Employee
{
public string Name {get;set;}
public int employee_id {get;set}
public int Age {get;set}
}
Class EmployeeCollection : IEnumerable, IEnumerable<Employee>, IOrderedEnumerable<Employee>
{
public Expression<Func<Employee, dynamic>> SortOrder {get;set;}
protected Dictionary<int,Employee> EmployeeById = new Dictionary<int,Employee>();
public void AddEmployee(Employee ePassed)
{
EmployeeById[ePassed.employee_id] = ePassed;
}
public IEnumerator<Employee> GetEnumerator()
{
foreach (int id in EmployeeByID.Keys)
{
yield return EmployeeById[id];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IOrderedEnumerable<Employee> CreateOrderedEnumerable<TKey>(Func<Employee, TKey> KeySelector, IComparer<TKey> comparer, bool descending)
{
if (descending)
return this.OrderByDescending(KeySelector, comparer);
else
return this.OrderBy(KeySelector, comparer);
}
public IEnumerable<Employee> OrderedObjects
{
if (this.SortOrder == null)
return (IEnumerable<Employee>)this; // No Sort Order applied
else
{
// How do I get the "parameters" from SortOrder to pass into CreateOrderedEnumerable?
throw new NotImplementedException();
}
}
}
Я хочу использовать синтаксис, подобный следующему...
EmployeeCollection.SortOrder = (x => x.Name);
foreach (Employee e in EmployeeCollection.OrderedObjects)
{
// Do something in the selected order
}
Существуют тысячи примеров того, как отбрасывать отсортированные, отфильтрованные и т. Д. Результаты в новый список, коллекцию, ObservableCollection и т. Д., Но если существующая коллекция уже реагирует на события, автоматически добавляет новые объекты в ответ на уведомления, действия пользователя, новые данные если он поступает с сервера и т. д., тогда вся эта функциональность либо "утеряна", либо должна быть "добавлена", чтобы новый List, Collection, ObservableCollection и т. д. прослушивал исходную коллекцию, чтобы как-то синхронизироваться со всеми различные обновления, свойства и т. д., которые оригинальная коллекция уже знает о них и обрабатывает... Я хочу, чтобы ОРИГИНАЛ "EmployeeCollection" просто разбирал объекты "Employee" в запрошенном SortOrder...
Я сделал "дикую догадку" о синтаксисе свойства "SortOrder", основываясь на желании сделать синтаксис свойства SortOrder похожим на часть orderby лямбда-выражений, с которой привыкли работать другие разработчики в команде, взглянув на методы расширения в System.Linq.Enumerable похожи на следующие:public static IOrderedEnumerable<TSource> OrderBy<ToSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);
Я новичок в Linq, lambda и т. Д. И заранее извиняюсь, если каким-то образом пропустил какой-то ключевой аспект деревьев Linq/Expression, предикатов, анонимных делегатов и т. Д., Которые другие считают очевидными.
1 ответ
Это работает, когда вы не используете ThenBy
операции типа (которые все IOrderedEnumerable<T>
интерфейс действительно добавляет). См. C#: Как реализовать IOrderedEnumerable
public class Employee
{
public string Name {get;set;}
public int employee_id {get;set;}
public int Age {get;set;}
}
public class EmployeeCollection : IEnumerable, IEnumerable<Employee>, IOrderedEnumerable<Employee>
{
public Func<Employee, object> SortOrder {get;set;}
public Func<Employee, bool> Filter {get;set;}
protected Dictionary<int,Employee> EmployeeById = new Dictionary<int,Employee>();
public void Add(Employee ePassed)
{
EmployeeById[ePassed.employee_id] = ePassed;
}
public IEnumerator<Employee> GetEnumerator()
{
var employees = EmployeeById.Keys.Select(id => this.GetEmployee(id));
if (Filter != null)
employees = employees.Where(Filter);
if (SortOrder != null)
employees = employees.OrderBy(SortOrder);
return employees.GetEnumerator();
}
public Employee GetEmployee(int id)
{
return EmployeeById[id];
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IOrderedEnumerable<Employee> CreateOrderedEnumerable<TKey>(Func<Employee, TKey> KeySelector, IComparer<TKey> comparer, bool descending)
{
throw new NotImplementedException();
}
}
// this is some code you might use to test this:
var EmployeeCollection = new EmployeeCollection
{
new Employee { employee_id = 1, Age = 20, Name = "Joe" },
new Employee { employee_id = 2, Age = 30, Name = "Thomas" },
new Employee { employee_id = 3, Age = 25, Name = "Robert" },
};
EmployeeCollection.SortOrder = x => x.Age;
EmployeeCollection.Filter = x => x.Name.Length > 4;
foreach (Employee e in EmployeeCollection)
{
// do something
}