Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Based on what everyone has contributed I have come up with the following. </p> <p>It provides bi-directional sorting as well solving the problem inside out. Meaning it didn't make much sense to me that a new Sorter need to be created for every unsorted list of a given type. Why can't this the unsorted list be passed into the sorter. This then means that we could create a signelton instance of the Sorter for our different types...</p> <p>Just an idea:</p> <pre><code>[TestClass] public class SpecifyUserDefinedSorting { private Sorter&lt;Movie&gt; sorter; private IQueryable&lt;Movie&gt; unsorted; [TestInitialize] public void Setup() { unsorted = from m in Movies select m; sorter = new Sorter&lt;Movie&gt;(); sorter.Register("Name", m1 =&gt; m1.Name); sorter.Register("Year", m2 =&gt; m2.Year); } [TestMethod] public void SortByNameThenYear() { var instructions = new List&lt;SortInstrcution&gt;() { new SortInstrcution() {Name = "Name"}, new SortInstrcution() {Name = "Year"} }; var sorted = sorter.SortBy(unsorted, instructions); var movies = sorted.ToArray(); Assert.AreEqual(movies[0].Name, "A"); Assert.AreEqual(movies[0].Year, 2000); Assert.AreEqual(movies[1].Year, 2001); Assert.AreEqual(movies[2].Name, "B"); } [TestMethod] public void SortByNameThenYearDesc() { var instructions = new List&lt;SortInstrcution&gt;() { new SortInstrcution() {Name = "Name", Direction = SortDirection.Descending}, new SortInstrcution() {Name = "Year", Direction = SortDirection.Descending} }; var sorted = sorter.SortBy(unsorted, instructions); var movies = sorted.ToArray(); Assert.AreEqual(movies[0].Name, "B"); Assert.AreEqual(movies[0].Year, 1990); Assert.AreEqual(movies[1].Name, "A"); Assert.AreEqual(movies[1].Year, 2001); Assert.AreEqual(movies[2].Name, "A"); Assert.AreEqual(movies[2].Year, 2000); } [TestMethod] public void SortByNameThenYearDescAlt() { var instructions = new List&lt;SortInstrcution&gt;() { new SortInstrcution() {Name = "Name", Direction = SortDirection.Descending}, new SortInstrcution() {Name = "Year"} }; var sorted = sorter.SortBy(unsorted, instructions); var movies = sorted.ToArray(); Assert.AreEqual(movies[0].Name, "B"); Assert.AreEqual(movies[0].Year, 1990); Assert.AreEqual(movies[1].Name, "A"); Assert.AreEqual(movies[1].Year, 2000); Assert.AreEqual(movies[2].Name, "A"); Assert.AreEqual(movies[2].Year, 2001); } [TestMethod] public void SortByYearThenName() { var instructions = new List&lt;SortInstrcution&gt;() { new SortInstrcution() {Name = "Year"}, new SortInstrcution() {Name = "Name"} }; var sorted = sorter.SortBy(unsorted, instructions); var movies = sorted.ToArray(); Assert.AreEqual(movies[0].Name, "B"); Assert.AreEqual(movies[1].Year, 2000); } [TestMethod] public void SortByYearOnly() { var instructions = new List&lt;SortInstrcution&gt;() { new SortInstrcution() {Name = "Year"} }; var sorted = sorter.SortBy(unsorted, instructions); var movies = sorted.ToArray(); Assert.AreEqual(movies[0].Name, "B"); } private static IQueryable&lt;Movie&gt; Movies { get { return CreateMovies().AsQueryable(); } } private static IEnumerable&lt;Movie&gt; CreateMovies() { yield return new Movie { Name = "B", Year = 1990 }; yield return new Movie { Name = "A", Year = 2001 }; yield return new Movie { Name = "A", Year = 2000 }; } } public static class SorterExtension { public static IOrderedQueryable&lt;T&gt; SortBy&lt;T&gt;(this IQueryable&lt;T&gt; source, Sorter&lt;T&gt; sorter, IEnumerable&lt;SortInstrcution&gt; instrcutions) { return sorter.SortBy(source, instrcutions); } } public class Sorter&lt;TSource&gt; { private readonly FirstPasses _FirstPasses; private readonly FirstPasses _FirstDescendingPasses; private readonly NextPasses _NextPasses; private readonly NextPasses _NextDescendingPasses; public Sorter() { this._FirstPasses = new FirstPasses(); this._FirstDescendingPasses = new FirstPasses(); this._NextPasses = new NextPasses(); this._NextDescendingPasses = new NextPasses(); } public void Register&lt;TKey&gt;(string name, Expression&lt;Func&lt;TSource, TKey&gt;&gt; selector) { this._FirstPasses.Add(name, s =&gt; s.OrderBy(selector)); this._FirstDescendingPasses.Add(name, s =&gt; s.OrderByDescending(selector)); this._NextPasses.Add(name, s =&gt; s.ThenBy(selector)); this._NextDescendingPasses.Add(name, s =&gt; s.ThenByDescending(selector)); } public IOrderedQueryable&lt;TSource&gt; SortBy(IQueryable&lt;TSource&gt; source, IEnumerable&lt;SortInstrcution&gt; instrcutions) { IOrderedQueryable&lt;TSource&gt; result = null; foreach (var instrcution in instrcutions) result = result == null ? this.SortFirst(instrcution, source) : this.SortNext(instrcution, result); return result; } private IOrderedQueryable&lt;TSource&gt; SortFirst(SortInstrcution instrcution, IQueryable&lt;TSource&gt; source) { if (instrcution.Direction == SortDirection.Ascending) return this._FirstPasses[instrcution.Name].Invoke(source); return this._FirstDescendingPasses[instrcution.Name].Invoke(source); } private IOrderedQueryable&lt;TSource&gt; SortNext(SortInstrcution instrcution, IOrderedQueryable&lt;TSource&gt; source) { if (instrcution.Direction == SortDirection.Ascending) return this._NextPasses[instrcution.Name].Invoke(source); return this._NextDescendingPasses[instrcution.Name].Invoke(source); } private class FirstPasses : Dictionary&lt;string, Func&lt;IQueryable&lt;TSource&gt;, IOrderedQueryable&lt;TSource&gt;&gt;&gt; { } private class NextPasses : Dictionary&lt;string, Func&lt;IOrderedQueryable&lt;TSource&gt;, IOrderedQueryable&lt;TSource&gt;&gt;&gt; { } } internal class Movie { public string Name { get; set; } public int Year { get; set; } } public class SortInstrcution { public string Name { get; set; } public SortDirection Direction { get; set; } } public enum SortDirection { //Note I have created this enum because the one that exists in the .net // framework is in the web namespace... Ascending, Descending } </code></pre> <p>Note if you didn't want to have a dependency on SortInstrcution it wouldn't be that hard to change.</p> <p>Hope this helps someone.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload