代码之家  ›  专栏  ›  技术社区  ›  CodeLikeBeaker

通用列表的动态排序标准

  •  2
  • CodeLikeBeaker  · 技术社区  · 17 年前

    这样做的目的是避免编写大量的if()语句。

    public override List<oAccountSearchResults> SearchForAccounts(oAccountSearchCriteria searchOptions)
    {
        List<oAccountSearchResults> results = Service.SearchForAccounts(searchOptions);
        results.Sort((a1, a2) => a2.AccountNumber.CompareTo(a1.AccountNumber));
        return results;
    }
    

    public override List<oAccountSearchResults> SearchForAccounts(oAccountSearchCriteria searchOptions, string sortCriteria)
    {
        List<oAccountSearchResults> results = Service.SearchForAccounts(searchOptions);
        if (sortCriteria == "AccountNumber")
        {
            results.Sort((a1, a2) => a2.AccountNumber.CompareTo(a1.AccountNumber));
        }
        else if (sortCriteria == "FirstName")
        {
            results.Sort((a1, a2) => a2.FirstName.CompareTo(a1.FirstName));
        }
        return results;
    }
    

    感谢大家的回复。

    这是我提出的最终解决方案。我在示例和Richards实现中使用了David的框架:

    using System;
    using System.Collections.Generic;
    
    namespace SortTest
    {
        class Program
        {
            static void Main(string[] args)
            {
    
    
                var results1 = Search(oObject => oObject.Value1);
    
                foreach (oObject o in results1)
                {
                    Console.WriteLine(o.Value1 + ", " + o.Value2);
                }
                Console.WriteLine(Environment.NewLine);
                var results2 = Search(oObject => oObject.Value2);
    
                foreach (oObject o in results2)
                {
                    Console.WriteLine(o.Value1 + ", " + o.Value2);
                }
    
    
                Console.ReadLine();
            }
    
            public static List<oObject> Search<T>(Func<oObject, T> keyExtract) where T: IComparable 
            {
                var results = new List<oObject>
                                                {
                                                    new oObject {Value1 = "A 1", Value2 = "B 2"},
                                                    new oObject {Value1 = "B 1", Value2 = "A 2"}
                                                };
    
                results.Sort((a, b) => keyExtract(a).CompareTo(keyExtract(b)));
                return results;
            }
        }       
        class oObject
        {
            public string Value1 { get; set; }
            public string Value2 { get; set; }
        }
    }
    
    6 回复  |  直到 17 年前
        1
  •  3
  •   Richard    17 年前

    如果呼叫者可以提供 表达 它提取用于比较的值,您可以在比较函数中调用该委托:

    public override List<oAccountSearchResults> SearchForAccounts<T>(
                  oAccountSearchCriteria searchOptions,
                  Func<oAccountSearchResults, T> keyExtract) where T : IComparable {
      List<oAccountSearchResults> results = Service.SearchForAccounts(searchOptions);
    
      results.Sort(a,b) => keyExtract(a).CompareTo(keyExtract(b)));
      return results;
    }
    
        2
  •  2
  •   David Yancey    17 年前

    你可以这样试试。我创建了一个示例对象用于测试目的:

    http://msdn.microsoft.com/en-us/library/bb534966.aspx

    public static class EnumerableExtension
    
        {
    
            public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> items, string property, bool ascending)
    
            {
    
                var myObject = Expression.Parameter(typeof (T), "MyObject");
    
    
    
                var myEnumeratedObject = Expression.Parameter(typeof (IEnumerable<T>), "MyEnumeratedObject");
    
    
    
                var myProperty = Expression.Property(myObject, property);
    
    
    
                var myLambda = Expression.Lambda(myProperty, myObject);
    
    
    
                var myMethod = Expression.Call(typeof (Enumerable), ascending ? "OrderBy" : "OrderByDescending",
    
                                               new[] {typeof (T), myLambda.Body.Type}, myEnumeratedObject, myLambda);
    
    
    
                var mySortedLambda =
    
                    Expression.Lambda<Func<IEnumerable<T>, IOrderedEnumerable<T>>>(myMethod, myEnumeratedObject).Compile();
    
    
    
                return mySortedLambda(items);
    
            }
    
        }
    

    class oObject
    
    {
    
        public string Value1 { get; set; }
    
        public string Value2 { get; set; }
    
    
    
    }
    

    然后,在您的程序中,您可以这样做:

    static void Main(string[] args)
    
            {
    
                var results = new List<oObject>
    
                                                {
    
                                                    new oObject {Value1 = "A", Value2 = "B"},
    
                                                    new oObject {Value1 = "B", Value2 = "A"}
    
                                                };
    
    
    
                IEnumerable<oObject> query = results.OrderBy("Value2", false);
    
                foreach (oObject o in query)
    
                {
    
                    Console.WriteLine(o.Value1 + ", " + o.Value2);
    
                }
    
                Console.WriteLine(Environment.NewLine);
    
                IEnumerable<oObject> query2 = results.OrderBy("Value1", false);
    
                foreach (oObject o in query2)
    
                {
    
                    Console.WriteLine(o.Value1 + ", " + o.Value2);
    
                }
    
                Console.ReadLine();
    
            }
    

    您的结果将是:

    问题1:

    B、 A

    B、 A

    A、 B

        3
  •  1
  •   Jan Remunda    17 年前

    public override List<oAccountSearchResults> SearchForAccounts(oAccountSearchCriteria searchOptions, Comparsion<oAccountSearchResults> sortCriteria)
    {
        List<oAccountSearchResults> results = Service.SearchForAccounts(searchOptions);
    
        results.Sort(sortCriteria);
    
        return results;
    }
    

    然后你可以像这样使用它:

    SearchForAccounts(searchOptionsObject, (x,y) => x.Property.CompareTo(y.Property));
    
        4
  •  1
  •   Jon Skeet    17 年前

    使用以下地图 String Comparer<oAccountSearchResults> 因此,您可以从字符串中计算出排序条件在代码术语中的含义。然后,您可以调用 Sort

    private static readonly Dictionary<String,Comparer<oAccountSearchResults>>
        SortOrders = new Dictionary<String,Comparer<oAccountSearchResults>>
    {
        { "AccountNumber", (a1, a2) => a2.AccountNumber.CompareTo(a1.AccountNumber) },
        { "FirstName", (a1, a2) => a2.FirstName.CompareTo(a1.FirstName) }
        // etc
    };
    
    public override List<oAccountSearchResults> SearchForAccounts(
        oAccountSearchCriteria searchOptions, string sortCriteria)
    {
        Comparer< oAccountSearchCriteria> sortOrder;
        if (!SortOrders.TryGetValue(sortCriteria, out sortOrder))
        {
            throw new ArgumentException("Unknown sort order " + sortCriteria);
        }
        List<oAccountSearchResults> results = Service.SearchForAccounts(searchOptions);
        results.Sort(sortOrder);
        return results;
    }
    
        5
  •  0
  •   Josh    17 年前

    Ayende Rahien在这里为这种行为提出了一个令人信服的理由: http://ayende.com/Blog/archive/2009/04/18/the-dal-should-go-all-the-way-to-ui.aspx