Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Dynamite: High Performace Dynamic Sorting Using Expressions

, 25 Sep 2008
Easy-to-use and high performance dynamic sorting of most type of sequences with SQL-like syntax, developed using System.Linq.Expression classes.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Linq.Expressions;
using System.Reflection;
using System.Diagnostics;
using Extensions;
using System.Text.RegularExpressions;
using System.Windows.Data;
using System.ComponentModel;
using Dynamite;
using Dynamite.Extensions;
using Dynamite.Data.Extensions;
using System.Collections;
using System.Data;
 
namespace DynamiteTester
{
    /// <summary>
    /// Interactive console test program for Dynamite dynamic sorting library
    /// </summary>
    class Program
    {
        public struct Point : IComparable
        {
            public int X { get; set; }
            public int Y { get; set; }
            public int? Height { get; set; }
            public Person Owner { get; set; }

            #region IComparable Members

            public int CompareTo(object obj)
            {
                if (obj == null) return -1;

                Point otherPoint = (Point)obj;
                return X.CompareTo(otherPoint.X);
            }

            #endregion

            public override string ToString()
            {
                return "{" + X + "," + Y + "}";
            }
        }

        public enum Sex
        {
            Male,
            Female
        }

        public class Person
        {
            public String Name { get; set; }
            public DateTime BirthDate { get; set; }
            public int Pets { get; set; }
            public Sex? Sex { get; set; }
            public Sex AttractedBy { get; set; }
            public DateTime? MarriedDate { get; set; }
            public Person Mother { get; set; }
            private Person Father;
            public bool IsMember;
            public Point? Coordinate { get; set; }
            public Point Point { get; set; }
        }

        static void Main(string[] args)
        {

           
            do
            {
                Console.WriteLine("Select comparison: ");
                Console.WriteLine("1=List<Person>.Sort((p1,p2) => String.Compare(p1.Name,p2.Name,...)");
                Console.WriteLine("2=List<Person>.Sort(ComparerBuilder<Person>.GetPropertyComparer(sortExpression, true)");
                Console.WriteLine("3=Reflection-Invoke-Based ");
                Console.WriteLine("4=List<Person>.Sort(sortExpression) using ComparerExtensions");
                Console.WriteLine("5=List<Person>.Sort using CreatePropertyComparer(sortExpression)");
                Console.WriteLine("6=List<Person>.Sort using.CreatePropertyComparerThroughEmit(sortExpression)");
                Console.WriteLine("7=List<Person>.AsQueryable().OrderBy(sortExpression)");
                Console.WriteLine("8=List<Person>.AsQueryable().OrderBy(p => p.Name)");
                Console.WriteLine("9=List<Person>.OrderBy(sortExpression)");
                Console.WriteLine("10=List<Person>.OrderBy(p => p.Name)");
                Console.WriteLine("11=CollectionViewSource.GetDefaultView(persons) sorting using SortDescription.");
                Console.WriteLine("12=CollectionViewSource.GetDefaultView(persons) sorting using CreateTypeComparer");
                Console.WriteLine("13=PersonDataTable.OrderBy(sortExpression)");
                Console.WriteLine("14=PersonDataTable.OrderBy(r => r.Name)");
                Console.WriteLine("15=PersonDataTable sorting using DataView.Sort=sortExpression");
                Console.WriteLine("Enter choice : ");

                String compType = Console.ReadLine();

                String sortExpression;

                Console.Write("Sort expression: ");
                sortExpression = Console.ReadLine();

                Console.Write("Count in each iteration (will be repeated until at least 100000 items have been sorted.) : ");
                int count = int.Parse(Console.ReadLine());


                Stopwatch watch = new Stopwatch();

                int totCount = 0;
                IEnumerator enumToVerify = null;

                while (totCount < 100000)
                {

                    List<Person> persons = new List<Person>(count);
                    Random rnd = new Random(12232322);
                    for (int i = 0; i < count; i++)
                    {
                        Person p = new Person()
                        {
                            Name = i % 50 == 0 ? null : (rnd.Next(2) == 0 ? "Person" : "person") + rnd.Next(count),
                            BirthDate = DateTime.Now.AddDays(-rnd.Next(36500)),
                            Pets = rnd.Next(4),
                            Sex = rnd.Next(3) == 0 ? Sex.Male : rnd.Next(2) == 0 ? Sex.Female : new Sex?(),
                            AttractedBy = rnd.Next(2) == 0 ? Sex.Male : Sex.Female,
                            MarriedDate = rnd.Next(100) > 0 ? new DateTime?(DateTime.Now.AddDays(-rnd.Next(36500))) : new DateTime?(),
                            Mother = i > 10 && rnd.Next(10) < 3 ? persons[rnd.Next(i)] : null,
                            Coordinate = rnd.Next(100) < 50 ? new Point() { X = rnd.Next(1000), Y = rnd.Next(1000) } : new Point?()
                        };
                        persons.Add(p);
                    }
                    PersonDataSet.PersonsDataTable personTable = new PersonDataSet.PersonsDataTable();
                    if (compType == "13" || compType == "14" || compType == "15" || compType == "16" || compType == "17")
                    {
                        for (int i = 0; i < count; i++)
                        {
                            Person person = persons[i];
                            PersonDataSet.PersonsRow row = personTable.AddPersonsRow(i, person.Name, person.BirthDate, person.Pets, person.MarriedDate.HasValue ? person.MarriedDate.Value : DateTime.Now);
                            if (person.MarriedDate.HasValue == false) { row.SetMarriedDateNull(); }
                        }
                    }

                    enumToVerify = null;
                    watch.Start();
                    Comparison<Person> compName;
                    switch (compType)
                    {
                        case "2":
                            compName = ComparerBuilder<Person>.GetPropertyComparison(sortExpression, true);
                            persons.Sort(compName);
                            break;
                        case "3":
                            Extensions.Extensions.Sort(persons, sortExpression);
                            break;
                        case "4":

                            ComparerExtensions.Sort(persons, sortExpression);
                            break;
                        case "5":
                            Comparison<Person> c = ComparerBuilder<Person>.CreatePropertyComparison(sortExpression, true);
                            persons.Sort(c);
                            break;
                        case "6":
                            Comparison<Person> c2 = ComparerBuilder<Person>.CreatePropertyComparisonThroughEmit(sortExpression, true);
                            persons.Sort(c2);
                            break;
                        case "7":
                            persons = new List<Person>(persons.AsQueryable().OrderBy(sortExpression));
                            break;
                        case "8":
                            persons = new List<Person>(persons.AsQueryable().OrderBy(p => p.Name));
                            break;
                        case "9":
                            persons = new List<Person>(persons.OrderBy(sortExpression));
                            break;
                        case "10":
                            persons = new List<Person>(persons.OrderBy(p => p.Name, StringComparer.CurrentCultureIgnoreCase));
                            break;
                        case "11":

                            ICollectionView personView = CollectionViewSource.GetDefaultView(persons);
                            personView.SortDescriptions.Add(new SortDescription(sortExpression, ListSortDirection.Ascending));
                            enumToVerify = personView.GetEnumerator();
                            break;
                        case "12":
                            ListCollectionView personView2 = (ListCollectionView)CollectionViewSource.GetDefaultView(persons);

                            personView2.CustomSort = (System.Collections.IComparer)ComparerBuilder<Person>.CreateTypeComparer(sortExpression);
                            enumToVerify = ((ICollectionView)personView2).GetEnumerator();
                            break;
                        case "13":
                            var lastRow = personTable.AsEnumerable().OrderBy(sortExpression).Last();
                            enumToVerify = personTable.AsEnumerable().OrderBy(sortExpression).GetEnumerator();
                            break;
                        case "14":
                            var lastRow2 = personTable.AsEnumerable().OrderBy(r => r.Field<String>("Name"), StringComparer.CurrentCultureIgnoreCase).ThenBy(r => r.Field<int>("Pets")).Last();
                            enumToVerify = personTable.AsEnumerable().OrderBy(r => r.Field<String>("Name"), StringComparer.CurrentCultureIgnoreCase).ThenBy(r => r.Field<int>("Pets")).GetEnumerator();
                            break;
                        case "15":
                            var view = personTable.DefaultView;
                            view.Sort = sortExpression;
                            enumToVerify = view.GetEnumerator();
                            break;
                        /*
                        case "18":
                            Phydeaux.Utilities.DynamicComparer<Person> dynComparer = new Phydeaux.Utilities.DynamicComparer<Person>(sortExpression);
                            persons.Sort(dynComparer.Comparer);
                            break;
                         */
                        case "20":
                            persons = new List<Person>(persons.OrderBy(p => p.AttractedBy));
                            break;
                        case "21":
                            persons = new List<Person>(persons.OrderBy(p => (int)p.AttractedBy));
                            break;
                        default:
                            compName = (Person p1, Person p2) => String.Compare(p1.Name, p2.Name, StringComparison.CurrentCultureIgnoreCase);
                            //compName = (Person p1, Person p2) => Nullable.Compare(p1.Coordinate, p2.Coordinate);
                            //compName = (Person p1, Person p2) => p1.Sex.CompareTo(p2.Sex);
                            persons.Sort(compName);
                            break;
                    }
                    watch.Stop();
                    if (enumToVerify == null)
                    {
                        enumToVerify = persons.GetEnumerator();
                    }

                    totCount += count;

                }
                watch.Stop();
                Console.WriteLine("Time to sort {0} persons {1} times by {3}: {2} ms", count, totCount / count, watch.ElapsedMilliseconds, sortExpression);
                Console.WriteLine("Press ENTER to enumerate results. Enter q to quit enumeration.");
                while (Console.ReadLine() != "q")
                {
                    int i = 0;
                    while (i < 10 && enumToVerify.MoveNext())
                    {
                        if (enumToVerify.Current is Person)
                        {
                            Person p = (Person)enumToVerify.Current;
                            Console.WriteLine("{0} {1} {2} {3} {4} ({5})", p.Name, p.AttractedBy, p.BirthDate, p.MarriedDate, p.Coordinate, p.Mother == null ? "none" : p.Mother.Name);
                            i++;
                        }
                        else if (enumToVerify.Current is DataRow)
                        {
                            DataRow r = (DataRow)enumToVerify.Current;
                            Console.WriteLine("{0} {1} {2} {3}", r["Name"], r["Pets"], r["BirthDate"], r.Field<DateTime?>("MarriedDate"));
                            i++;
                        }
                        else if (enumToVerify.Current is DataRowView)
                        {
                            DataRow r = ((DataRowView)enumToVerify.Current).Row;
                            Console.WriteLine("{0} {1} {2} {3}", r["Name"], r["Pets"], r["BirthDate"], r.Field<DateTime?>("MarriedDate"));
                            i++;
                        }
                    }
                    Console.WriteLine("Press ENTER to show more results. Enter q to quit enumeration.");
                }
                Console.WriteLine("Press ENTER to go to main menu. Enter q to quit program. ");
            } while (Console.ReadLine() != "q");
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Henrik Jonsson
Software Developer
Sweden Sweden
Henrik Jonsson is a Microsoft Professional Certified Windows Developer (MCPD) that currently works as an IT consultant in Västerås, Sweden.
 
Henrik has worked in several small and large software development projects in various roles such as architect, developer, CM and tester.
 
He regularly reads The Code Project articles to keep updated about .NET development and get new ideas. He has contributed with articles presenting some useful libraries for Undo/Redo, Dynamic Linq Sorting and a Silverlight 5 MultiBinding solution.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 25 Sep 2008
Article Copyright 2008 by Henrik Jonsson
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid