如何从基于 OrderBy “属性”的集合中返回 IOrderedEnumerable

本文关键字:集合 IOrderedEnumerable 返回 属性 OrderBy | 更新日期: 2023-09-27 18:36:43

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
}

有成千上万的示例说明如何将排序,过滤等结果抛到新的List,Collection,ObservableCollection等中。 但是,如果您现有的集合已经响应事件,自动添加新对象以响应通知,用户操作,来自服务器的新数据等,那么所有这些功能要么"丢失",要么必须"添加"才能使新的List,Collection,ObservableCollection等收听原始集合,以便以某种方式与所有各种更新保持同步, 原始集合已经知道并处理的属性等... 我希望能够让原始的"员工集合"简单地在请求的排序顺序中分发出"员工"对象......

我对"SortOrder"属性的语法进行了"疯狂的猜测",基于希望使 SortOrder 属性的语法类似于团队中其他开发人员习惯使用的 lambda 表达式的 orderby 部分,方法是查看 System.Linq.Enumerable 中的扩展方法,类似于以下内容: public static IOrderedEnumerable<TSource> OrderBy<ToSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);

我是Linq,

lambda等的新手,如果我以某种方式错过了Linq/表达式树,谓词,匿名委托等其他人认为显而易见的某些关键方面,请提前道歉。

如何从基于 OrderBy “属性”的集合中返回 IOrderedEnumerable

当您不使用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
}