实现ICompare接口的通用对象比较类

        当我们使用Array及ArrayList的Sort方法或BinarySearch方法时,通常需要提供一个实现ICompare接口的类。虽然实现ICompare接口并不复杂但是重复这些写法基本相同的代码,让人感觉到索然无味,那有没有一种通用的方法一劳永逸呢?对于这个问题dannyr兄分享了他的方法《任意对象数组ArrayList的排序法(可自定义排序字段、排序方向) 》。但是dannyr兄的方法有几个小问题:
  1. 不能按多个属性或字段排序。
  2. 如果指定两个对象的属性的值一样(不是两个对象一样),则按这个属性排序后,每排一次对象的位置就变化一下,不稳定。这会对应用到实际的项目中造成困扰。
  3. 不能指定属性排序时的类型(只能按字符串比较),如作为int来比较。

        因此又把自己以前写的代码整理了一下(从实际项目的代码中RIP出来的),帖出来和大家分享。

实现类代码:


/// <summary>
/// 通用对象比较类,一般用于对一个对象数组按属性排序或查询
/// </summary>

public class ObjectCompare : System.Collections.IComparer
{
    SortEntry[] _sortEntrys;
    
/// <summary>
    
/// 构造函数,制定排序方法
    
/// </summary>
    
/// <param name="type">对象的类型</param>
    
/// <param name="args">排序方法</param>

    public ObjectCompare(Type type, params SortEntry[] args)
    
{
        _sortEntrys 
= args;

        
//为防止因为指定的排序字段的值一样而造成每次的排序结果不同,再加属性和字段做为辅助
        int j = args.Length;

        PropertyInfo[] pis 
= type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
        FieldInfo[] fis 
= type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);

        _sortEntrys 
= new SortEntry[_sortEntrys.Length + pis.Length + fis.Length];

        args.CopyTo(_sortEntrys, 
0);

        
foreach (PropertyInfo pi in pis)
            _sortEntrys[j
++= new SortEntry(pi.Name, pi.PropertyType, false);
        
foreach (FieldInfo fi in fis)
            _sortEntrys[j
++= new SortEntry(fi.Name, fi.FieldType, false);
    }



    
IComparer Members

    
public object GetObjectPropertyValue(object obj, string propertyName)
}


/// <summary>
/// 排序方式设定
/// </summary>

public struct SortEntry
{
    
/// <summary>
    
/// 构造函数
    
/// </summary>
    
/// <param name="propertyName">属性名</param>
    
/// <param name="value">是否倒序</param>

    public SortEntry(string propertyName) : this(propertyName, typeof(string), false{ }

    
/// <summary>
    
/// 构造函数
    
/// </summary>
    
/// <param name="propertyName">属性名</param>
    
/// <param name="value">是否倒序</param>

    public SortEntry(string propertyName, bool isDescend) : this(propertyName, typeof(string), isDescend) { }

    
/// <summary>
    
/// 构造函数
    
/// </summary>
    
/// <param name="propertyName">属性名</param>
    
/// <param name="value">是否倒序</param>
    
/// <param name="type">属性类型</param>

    public SortEntry(string propertyName, Type type, bool isDescend)
    
{
        
if (propertyName + "" == "")
            
throw new Exception("属性名不能为空!");

        
if (type == null)
            
throw new Exception("属性的类型不能为空!");
        _propertyName 
= propertyName;
        _descend 
= isDescend;
        _type 
= type;
    }


    
/// <summary>
    
/// 属性名
    
/// </summary>

    string _propertyName;
    
public string PropertyName get return _propertyName; } set { _propertyName = value; } }

    
/// <summary>
    
/// 是否倒序
    
/// </summary>

    bool _descend;
    
public bool Descend get return _descend; } set { _descend = value; } }

    Type _type;
    
/// <summary>
    
/// 属性的类型
    
/// </summary>
    
/// <value></value>

    public Type ProeprtyType get return _type; } set { _type = value; } }
}


测试代码:


struct Test
    
{
        
public Test(string a, int b, string c)
        
{
            A 
= a;
            B 
= b;
            C 
= c;
        }

        
public string A;
        
public int B;
        
public string C;
    }

    
class Program
    
{
        
static void Main(string[] args)
        
{
            ArrayList al 
= new ArrayList();
            
for (int i = 0; i < 10; i++)
            
{
                al.Add(
new Test("A" + i, 1"1"));
                al.Add(
new Test("C" + i, 2"2"));
                al.Add(
new Test("B" + i, 1"3"));
                al.Add(
new Test("A" + i, 3"4"));
                al.Add(
new Test("D" + i, 2"5"));

            }


            Console.WriteLine(
"默认排序1");
            al.Sort(
new ObjectCompare(typeof(Test),new SortEntry("A")));
            Output(al);
            
            Console.WriteLine(
"默认排序2");
            al.Sort(
new ObjectCompare(typeof(Test)));
            Output(al);

            Console.WriteLine(
"按属性A排序1");
            al.Sort(
new ObjectCompare(typeof(Test),new SortEntry("A")));
            Output(al);

            Console.WriteLine(
"按属性A排序2");
            al.Sort(
new ObjectCompare(typeof(Test),new SortEntry("A")));
            Output(al);

            Console.WriteLine(
"按属性B排到序1");
            al.Sort(
new ObjectCompare(typeof(Test),new SortEntry("B"typeof(int), true)));
            Output(al);

            Console.WriteLine(
"按属性B排到序2");
            al.Sort(
new ObjectCompare(typeof(Test),new SortEntry("B"typeof(int), true)));
            Output(al);

            Console.ReadLine();
        }


        
static void Output(ArrayList al)
        
{
            
foreach (Test obj in al)
            
{
                Console.WriteLine(
"A:{0}\tB:{1}\tC:{2}", obj.A, obj.B, obj.C);
            }

            Console.WriteLine(
"------");
            Console.Write(
"\r\n\r\n\r\n");
        }

    }
posted @ 2006-03-02 23:51  torome  阅读(415)  评论(0)    收藏  举报