2009-01-26 94 views
2

我有一個自定義對象(例如只爲了便於理解代碼)...從字符串訪問對象屬性申述

public class MyClass 
{ 
    private string name; 
    private int increment; 
    private Guid id; 

    public string Name 
    { 
     get { return name; } 
     set { name = value; } 
    } 

    public int Increment 
    { 
     get { return increment; } 
     set { increment = value; } 
    } 

    public Guid Id 
    { 
     get { return id; } 
     set { id = value; } 
    } 
} 

...這個類的一個自定義集合...

public class MyClassCollection : Collection<MyClass> 
{ 

} 

我一直在尋找寫這將有下面的公共方法的集合排序例行...

public void Sort(params string[] sortProperties) 
    { 
     if (sortProperties == null) 
     { 
      throw new ArgumentNullException("sortProperties", "Parameter must not be null"); 
     } 

     if ((sortProperties.Length > 0) && (Items.Count > 1)) 
     { 
      foreach (string s in sortProperties) 
      { 
     // call private sort method 
       Sort(s); 
      } 
     } 
    } 

...和私營排序方法將採取屬性名的參數...

private void Sort(string propertyName) 
    { 

    } 

我想要做的是能在一組屬性名稱傳遞給方法是什麼?

 MyClassCollection current = new MyClassCollection(); 

     // setup a objects in the collection 
     current = GetCollectionData(); 

     // sort by Name, then by Increment 
     current.Sort("Name", "Increment"); 

使用傳遞給方法的屬性名稱我希望能夠檢查它是否具有該名稱的屬性,如果是這樣的話,找出它是什麼類型,然後通過它的一種運行。

這是我目前得到的臨時解決方法是...

private void Sort(string propertyName) 
    { 
     // convert to List 
     List<MyClass> myCurrentClass = Items as List<MyClass>; 

     // sort 
     if (myCurrentClass != null) 
     { 
      switch (propertyName) 
      { 
       case "Name": 
        myCurrentClass.Sort(delegate(MyClass myClassOne, MyClass myClassTwo) 
           { 
            return 
             Comparer<string>.Default.Compare(myClassOne.Name, 
                      myClassTwo.Name); 
           } 
         ); 
        break; 

       case "Increment": 
        myCurrentClass.Sort(delegate(MyClass myClassOne, MyClass myClassTwo) 
           { 
            return 
             Comparer<int>.Default.Compare(myClassOne.Increment, 
                     myClassTwo.Increment); 
           }); 
        break; 
      } 
     } 
    } 

...但最好我想在下面的屬性的類型轉換(字符串,整數等)和使用不同數量的委託調用類型進行排序。我環顧四周,但我沒有找到任何指向正確方向的東西。我看了看反射,但看不到任何能夠幫助我的東西。

這甚至可能嗎?如果是這樣,怎麼樣?!

乾杯!

回答

1

昨天晚上我碰到問題一段時間後,希望在火車回家後,我決定,我會試着打一個回答。使用Jon的指針和弗雷德裏克使用的PropertyInfo類的組合,並保持對潛在對象類型轉換原來的想法,這是我想出了...

private void Sort_version2(string propertyName) 
    { 
     // convert to list 
     List<MyClass> myCurrentClass = Items as List<MyClass>; 

     string typeOfProperty; 
     PropertyInfo pi; 

     // sort 
     if ((myCurrentClass != null) && (MyClass.HasDetailAndExtract(propertyName, out typeOfProperty, out pi))) 
     { 
      switch(typeOfProperty) 
      { 
       case "System.String": 
        myCurrentClass.Sort(delegate(MyClass one, MyClass two) 
              { 
               return 
                Comparer<string>.Default.Compare(pi.GetValue(one, null).ToString(), 
                        pi.GetValue(two, null).ToString()); 
              }); 
        break; 

       case "System.Int32": 
        myCurrentClass.Sort(delegate (MyClass one, MyClass two) 
              { 
               return 
                Comparer<int>.Default.Compare(
                 Convert.ToInt32(pi.GetValue(one, null)), 
                 Convert.ToInt32(pi.GetValue(two, null))); 
              }); 
        break; 
       default: 
        throw new NotImplementedException("Type of property not implemented yet"); 
      } 
     } 
    } 

我記錄的思維過程並在my blog更多細節讓我知道你的想法!

感謝Jon和弗雷德裏克的幫助:-)

3

的反思將是要走的路 - 看Type.GetProperty(string name)。之後創建正確的比較器可能會非常棘手 - 您可能需要編寫一個泛型方法,然後根據屬性類型使用反射來調用該方法。這一切都變得很棘手,我擔心 - 但這絕對是可行的。

+0

你不能使用常規的,非通用的Comparer這需要對象作爲參數? – 2009-01-26 14:46:18

+0

可能。不能說我曾經使用非通用形式 - 甚至不知道它的存在! – 2009-01-26 14:54:02

3
private void Sort(string propertyName) 
{ 
    List<MyClass> myCurClass = ... 

    myCurClass.Sort(delegate(MyClass left, MyClass right){ 

     PropertyInfo lp = typeof(MyClass).GetProperty (propertyName); 

     Comparer.Default.Compare (pi.GetValue(left), pi.GetValue(right)); 


    }); 
} 

我認爲這應該讓你開始。 :) (未經測試,也沒有編譯,但你會得到這個想法)