2016-04-03 161 views
0

我有一個通用列表。我必須根據列表項的屬性值過濾列表。項目類型直到運行時才知道。如何通過c#中的反射過濾通用列表

我必須通過反射找到項目類型,然後需要過濾。

請幫助我的任何想法或示例

謝謝。

+0

你能加你是一個什麼樣的代碼示例試圖做/你試過了什麼? –

+0

您可以使用列表中的'.OfType'按類型進行過濾:'list.OfType ()' - 但它不太可能覆蓋您的「通過反射」要求。 –

+0

「項目類型直到運行時才知道」 - 您在運行時用什麼機制來指定項目類型?你怎麼知道類型(在運行時)有你想要的屬性?你對'通用列表'定義的基類型是什麼,或者它只是'var list = new [];'而且你沒有使用正確的術語。包括你的代碼到目前爲止將有助於回答這些問題。 –

回答

1

我希望這有助於

通任何名單,並指定屬性名和濾波方法

 private IList FilterList(IList list, string propName, Predicate<object> filterMethod) { 
     var result = new List<object>(); 
     foreach (var item in list) { 
      var value = item.GetType().GetProperty(propName).GetValue(item); 
      if (filterMethod(value)) { 
       result.Add(item); 
      } 
     } 
     return result; 

    } 

例子:

var result = FilterList(list, "Age", age => (int)age >= 18); 

你可以開發它,使其充分動態​​

+0

謝謝@ yousif.aljamri, 如果我事先知道屬性類型,則您的解決方案正在運行。從你的例子中,如果我不把Age放到int中,它就不起作用。 我不知道屬性類型。我如何過濾? –

+0

@BulbulAhmed你的過濾器有多詳細? ,並從它的來源?,如果它是簡單的文本過濾器,它更容易 –

1

如果列表是通用的,那麼應該在編譯時至少知道一個基類型。

如果基本類型包含屬性 - 只需使用它。

如果只有某些子類型(理想情況下爲一個)包含您感興趣的屬性,則可以在列表上執行cast,然後使用您的屬性。

list.Cast<Derived>().Select(i => i.Property == "val"); 

如果這是不正常(比如列表的類型有一個包含屬性和其他人不很多派生類型),您可以使用動態與try/catch塊。

list.Select(i => { 
        try 
        { 
         dynamic item = i; 
         return item.Prop == "value"; 
        } 
        catch(RuntimeBinderException) //this type doesn't contain the property 
        { 
         return false; 
        } 
       }); 
+0

Thanks @Bond, 我只能通過反射知道派生類型。我如何將它轉換爲它的類型列表? –

0

試試這個。它可以確定列表是否是某種指定類型的列表。基於此,您應該能夠篩選任何特定類型。

public class TypeA 
{ } 
public class TypeB 
{ } 

public class GenericFilter 
{ 
    public bool IsOfType<T>(IEnumerable<dynamic> objectToInspect) 
    { 
     var genericType = objectToInspect.GetType().GenericTypeArguments[0]; 
     return genericType == typeof(T); 
    } 
} 


[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void IdentifiesExpectedType() 
    { 
     var classToInspect = new List<TypeA>(); 
     var filter = new GenericFilter(); 
     Assert.IsTrue(filter.IsOfType<TypeA>(classToInspect)); 
    } 

    [TestMethod] 
    public void RejectsNonMatchingType() 
    { 
     var classToInspect = new List<TypeA>(); 
     var filter = new GenericFilter(); 
     Assert.IsFalse(filter.IsOfType<TypeB>(classToInspect)); 
    } 
} 

該作品一樣好:

public bool IsOfType<T>(IEnumerable<dynamic> listToFilter) 
{ 
    return (listToFilter as IEnumerable<T>) != null; 
} 

這將名單和他們組的列表爲Dictionary<Type, List<List<dynamic>>所有每個鍵列表的是那類型。這樣,您可以通過從字典中檢索它們來選擇T類型的列表。

public Dictionary<Type, List<List<dynamic>>> GroupListsByType(List<List<dynamic>> lists) 
    { 
     var types = lists.Select(list => list.GetType().GenericTypeArguments[0]).Distinct().ToList(); 
     var grouped = new Dictionary<Type, List<List<dynamic>>>(); 
     types.ForEach(type => 
     { 
      grouped.Add(type, new List<List<dynamic>>()); 
      grouped[type].AddRange(lists.Where(list=>list.GetType().GenericTypeArguments[0] == type)); 
     }); 
     return grouped; 
    } 

(我不是質疑「爲什麼。」我不知道我是否會推薦這一點,但它是有趣的寫。)