This message was discovered on ASPFriends.com 'aspngarchitecture' list.
| Daniel Wilson |
Hello, A few days ago someone, Bryan? maybe, posted a slightly modified version of the ECC design pattern called MCC. Well anyways, I want go over the pattern again but basically it had a custom collection of a User Created Class referred to as ObjectCollection. In it he suggested adding a method Sort() that allowed objects to be sorted based on a property. How would this function look (some sample code would be great :) See the reason I am asking is that most examples I have seen have special sort functions for EACH property or in my case I have an enum with possible field name (property names) to sort on (i.e. MyCollection.Sort(MyCollection.SortOn field) where SortOn is an enum inside MyCollection Class.) However, in his pattern he has a general collection, ObjectCollection, with ONE sort method that will sort on any arbitrary property of the collected classes. I just don't see how one could do that. Either A I read the pattern wrong or B I am missing something. I would really appreciate it if Bryan or anyone else will help me out on this matter.
Thanks in advance, Daniel Wilson
|
|
| |
| |
| Bryan Costanich |
Part 3
#endregion
//========================================================================
//======================================================================== #region -= public properties =-
//---- SortPropertyName
public string SortPropertyName
{
get { return m_strSortPropertyName; }
set { m_strSortPropertyName = value; }
}
#endregion
//========================================================================
}
//========================================================================
#endregion
//========================================================================
}
//======================================================================== }
|
|
| |
|
| |
| Bryan Costanich |
Part 2
//======================================================================== #region -= public properties =-
//---- SortPropertyName
public string SortPropertyName
{
get { return this.m_objComparer.SortPropertyName; }
}
//---- SortOrder
public SortOrders SortOrder
{
get { return this.m_objSortOrder; }
}
#endregion
//========================================================================
#endregion
//========================================================================
//======================================================================== #region -= internal helper classes =-
//======================================================================== protected internal sealed class PropertyComparer : IComparer
{
//======================================================================== #region -= private declarations =-
private string m_strSortPropertyName;
#endregion
//========================================================================
//======================================================================== #region -= public methods =-
//======================================================================== /// <summary>
/// Performs a case-sensitive comparison of two objects of the same type and returns a value indicating whether
/// one is less than, equal to or greater than the other.
/// </summary>
/// <param name="x">The first object to compare.</param>
/// <param name="y">The second object to compare.</param>
/// <returns>-1 if a is less than b, 0 if equal, 1 if a is greater than b</returns>
public int Compare(object x, object y)
{
//---- if there is no property to compare on, just peter out
if(m_strSortPropertyName =null || m_strSortPropertyName == "")
throw new Exception("need a property to sort by");
//---- compare the properties using the default comparer
return Comparer.Default.Compare(GetPropertyValueRecursive(x, m_strSortPropertyName),
GetPropertyValueRecursive(y, m_strSortPropertyName));
}
//========================================================================
#endregion
//========================================================================
//======================================================================== #region -= private/protected methods =-
//======================================================================== /// <summary>
/// Returns a property for a nested set of objects such as object1.object2.object3.object4.property
/// </summary>
/// <param name="objectIn">the object to look in</param>
/// <returns>the property of the last object</returns>
private object GetPropertyValueRecursive(object objectIn, string propertyName)
{
//---- declare vars
string[] strAryTypes propertyName.Split('.'); //split out the properties (RootObject, Child, ChildChild, Property)
int intCurrentIndex = 0; // start at the second type (object.xType1)
object objCurrentType objectIn; // start at the root object
//---- walk down the tree
while(intCurrentIndex < strAryTypes.Length)
{
//---- get the next type down the tree
objCurrentType objCurrentType.GetType().GetProperty(strAryTypes[intCurrentIndex]).GetValue( objCurrentType, null);
//---- increment the counter
intCurrentIndex++;
}
//---- now the objCurrentType will have the last property
return objCurrentType;
}
//========================================================================
|
|
| |
| |
| Chris Melvin |
Bryan, Thanks for posting the custom Collection sort code. Works great when deriving from ArrayList.
Someone mentioned that the collection class could be derived from any class implementing ICollection, such as CollectionBase or DictionaryBase. I ran into some issues when deriving from any ICollection class that does not implement a Sort method. Sort is not a method in the ICollection interface.
Has anyone has tackled implementing a sort method in a CollectionBase or DictionaryBase derived collection class?
-------------------------------- From: Chris Melvin
|
|
| |
|
| |
| Chris Melvin |
Bryan, oops, my mistake, it does work with CollectionBase. Just have to change this.Sort and this.Reverse to this.InnerList.Sort and this.InnerList.Reverse.
Thanks again for posting the code!
-------------------------------- From: Chris Melvin
|
|
| |
|
|
| |
| Bryan Costanich |
Daniel,
Here is some robust code to do collection sorting. It will not only sort on a property, but will also work for subitems, ie, sort on Object.Object.Object.Property. It uses the internal ArrayList.Sort method with a custom comparer. The sort method is a (n log2 n) algorithm so it's pretty fast and scales well.
You'll notice that the custom collection is derived from an ArrayList, but could just as well be derived from any object the implements ICollection. In the pattern I mentioned ArrayList, but I need to update that as well because it should be any ICollection object.
Additionally, the collection here is a generic one and not strongly typed. If you wish to implement a strongly-typed collection (which are damn cool) then you will probably want to create your own custom collection class and derive from CollectionBase or DictionaryBase. In order to do it yourself you are looking at a lot of code, and those objects already serve as a good base. The last time I was working out at Microsoft I spoke to someone on the .net team, I forget who, but they recommended deriving from those base classes. I personally agree, the majority of the plumbing is already present and tested and there will be no surprises.
You can download the entire project with the code at http://codebox.wowzer.net/Code/CollectionSort.zip <http://codebox.wowzer.net/Code/CollectionSort.zip> it has the collection object and all the objects needed to test it. just unzip it into your websites directory, create the folder as an app in IIS and hopefully it will work.
Anyway, here is the code for the collection object itself:
PART 1 (have to split cause message is too long)
using System;
using System.Collections;
using System.Reflection;
namespace Sicily.Test.Classes
{
//======================================================================== /// <summary>
/// A generic item collection (not strongly typed) that enables sort on properties of the objects in it.
/// </summary>
public class ItemCollection : ArrayList
{
//======================================================================== public enum SortOrders
{
None,
Ascending,
Descending
}
//========================================================================
//======================================================================== #region -= private declarations =-
protected PropertyComparer m_objComparer;
protected SortOrders m_objSortOrder;
#endregion
//========================================================================
//======================================================================== public ItemCollection()
{
m_objComparer = new PropertyComparer();
m_objSortOrder = SortOrders.None;
}
//========================================================================
//======================================================================== #region -= public methods =-
//======================================================================== /// <summary>
/// Sorts on a property on an item in the collection. Works for nested properties as well.
/// <note>
/// Sorts ascending
/// </note>
/// </summary>
/// <param name="propertyName"></param>
public void Sort(string propertyName)
{
this.Sort(propertyName, SortOrders.Descending);
}
//========================================================================
//======================================================================== /// <summary>
/// Sorts on a property on an item in the collection. Works for nested properties as well.
/// </summary>
/// <param name="propertyName"></param>
public void Sort(string propertyName, SortOrders sortOrder)
{
//---- set the sort order property
this.m_objSortOrder = sortOrder;
//---- set the property to sort by
m_objComparer.SortPropertyName propertyName;
//---- sort the collection
this.Sort(m_objComparer);
//---- if it's supposed to be descending, reverse the array
if (sortOrder==SortOrders.Ascending)
{ this.Reverse(); }
}
//========================================================================
Have to split here cause message is to long.
-----Original Message----- From: Daniel Wilson [mailto:Click here to reveal e-mail address] Sent: Tuesday, July 09, 2002 1:19 PM To: aspngarchitecture Subject: [aspngarchitecture] Sort Based on Property.
Hello,
A few days ago someone, Bryan? maybe, posted a slightly modified version of the ECC design pattern called MCC. Well anyways, I want go over the pattern again but basically it had a custom collection of a User Created Class referred to as ObjectCollection. In it he suggested adding a method Sort() that allowed objects to be sorted based on a property. How would this function look (some sample code would be great :)
See the reason I am asking is that most examples I have seen have special sort functions for EACH property or in my case I have an enum with possible field name (property names) to sort on (i.e. MyCollection.Sort(MyCollection.SortOn field) where SortOn is an enum inside MyCollection Class.) However, in his pattern he has a general collection, ObjectCollection, with ONE sort method that will sort on any arbitrary property of the collected classes. I just don't see how one could do that. Either A I read the pattern wrong or B I am missing something. I would really appreciate it if Bryan or anyone else will help me out on this matter.
Thanks in advance,
Daniel Wilson
| [aspngarchitecture] member Click here to reveal e-mail address = YOUR ID | http://www.asplists.com/asplists/aspngarchitecture.asp = JOIN/QUIT | http://www.asplists.com/search = SEARCH Archives
|
|
| |
|
| |
| Daniel Wilson |
Hey brian I was using the code you sent me and after a little inspection came across a part that I was hoping you or anyone could shed some light on for me. Here is the section:
//=========================================================================
/// <summary>
/// Sorts on a property on an item in the collection. Works for nested properties as well.
/// <note>
/// Sorts ascending
/// </note>
/// </summary>
/// <param name="propertyName"></param>
public void Sort(string propertyName)
{
this.Sort(propertyName, SortOrders.Descending);
}
//========================================================================
Notice how in the note section in the comments it states that this function "sorts ascending" - Why would the internal implementation for the sort use SortOrders.Descending . This doesn't seem right because for the users of my collection ObjectCollection.Sort("ID", SortOrders.Descending) is the way for them to sort my collection in accending order? Am I missing something?
Thanks
Daniel O Wilson
|
|
| |
|
| |
| Bryan Costanich |
No, you're not missing anything, I just made a typo.
Thanks for the catch.
-----Original Message----- From: Daniel Wilson [mailto:Click here to reveal e-mail address] Sent: Thursday, July 11, 2002 12:24 PM To: aspngarchitecture Subject: [aspngarchitecture] RE: Sort Based on Property.
Hey brian I was using the code you sent me and after a little inspection came across a part that I was hoping you or anyone could shed some light on for me.
Here is the section:
//=========================================================================
/// <summary>
/// Sorts on a property on an item in the collection. Works for nested properties as well.
/// <note>
/// Sorts ascending
/// </note>
/// </summary>
/// <param name="propertyName"></param>
public void Sort(string propertyName)
{
this.Sort(propertyName, SortOrders.Descending);
}
//========================================================================
Notice how in the note section in the comments it states that this function "sorts ascending" - Why would the internal implementation for the sort use SortOrders.Descending . This doesn't seem right because for the users of my collection ObjectCollection.Sort("ID", SortOrders.Descending) is the way for them to sort my collection in accending order? Am I missing something?
Thanks
Daniel O Wilson
| [aspngarchitecture] member Click here to reveal e-mail address = YOUR ID | http://www.asplists.com/asplists/aspngarchitecture.asp = JOIN/QUIT | http://www.asplists.com/search = SEARCH Archives
|
|
| |
|
|
|
|
|