2013-12-13 56 views
1

我是新來的反思,所以請原諒我noob問題。如何創建一個帶有兩個參數,一個通用列表和一個字符串的方法,然後查找該列表中任何屬性值與該字符串匹配的所有項目。反射來過濾列表<T>

因此,例如,我們有3個屬性的對象,我把這個對象傳遞給方法和搜索字符串列表,並返回其中任何屬性可能包含搜索字符串對象的列表。

我可以這樣做:

var temp = list.AsQueryable().Where("SomeField == 1").Select("it"); 

但我怎麼能做出這種方法一般,所以我可以將對象傳遞給它的任何名單?

在此先感謝...

+0

你爲什麼要這麼做?這是一種想要做的奇怪的事情,也許有更好的方法來做到這一點。 –

+0

我建立了JTable中過濾器在那裏我可以輸入文本並篩選基於文本的網格。 jTable使用對象列表。我想建立一個通用的方法,所以我可以反覆使用它。 – w2olves

回答

1

如果使用的是動態的LINQ,試試這個

public static IEnumerable<T> Filter<T>(IEnumerable<T> source, string searchStr) 
{ 
    var propsToCheck = typeof (T).GetProperties().Where(a => a.PropertyType == typeof(string)); 

    var filter = propsToCheck.Aggregate(string.Empty, (s, p) => (s == string.Empty ? string.Empty : string.Format("{0} OR ", s)) + string.Format("{0} == @0", p.Name)); 

    var filtered = source.AsQueryable().Where(filter, searchStr); 
    return filtered; 
} 
+0

太棒了,如何擴展這個以允許.Contains擴展?所以,而不是100%的匹配,我可以打開包含字符串的對象? – w2olves

+0

只需將「{0} == @ 0」更改爲「{0} .Contains(@ 0)」,但應檢查null,因此如果某些屬性可能爲null,請使用「{0}!= null && { 0}。載(@ 0)」 – pil0t

1

使用Type.GetProperties()獲取對象的所有屬性。使用PropertyInfo.GetValue()來獲取給定對象中給定屬性的值。你需要弄清楚你想如何將字符串匹配到日期時間,數字或其他複雜對象。把它放在一個函數中,如bool IsMatch(this object obj, string val)。然後你可以過濾你的列表,如list.Where(x => x.IsMatch("something"))

+0

你能舉個例子嗎? – w2olves

+0

我給你,你需要使它工作的所有信息,但顯然其他人是點更加絕望:)。 – fejesjoco

+0

我認爲這裏的重點不是吹噓理論知識。它很容易說出一個清單並對其進行過濾。其他人可能是爲了SOF的精神,給出一個答案,如果不是這樣,爲什麼要使用SOF?所有的答案都可以在Local Barnes和Noble上得到嗎? – w2olves

1

在這裏你去隊友:

private static void Main(string[] args) 
    { 
     var list = new List<object> {new {prop1 = "A", prop2 = "B"},new {prop3 = "B", prop4 = "C"}}; 
     var subList = SearchForStringInProperties(list, "C"); 
    } 

    private static IEnumerable<object> SearchForStringInProperties(IEnumerable<object> list, string searchString) 
    { 
     return from obj in list where FindStringInObjProperties(obj, searchString) select obj; 
    } 

    private static bool FindStringInObjProperties(object obj, string searchString) 
    { 
     return obj.GetType().GetProperties().Any(property => obj.GetType().GetProperty(property.Name).GetValue(obj).ToString().Equals(searchString)); 
    } 
+0

如果prop1爲空,該怎麼辦? – w2olves

+0

好一點,和好斑點,然而,這是一個展示的概念,而不是生產準備代碼示例代碼。當然你也可以很容易地檢查null。 謝謝你指出。 –

+0

謝謝你,我從來沒有想過這樣做......謝謝教育 – w2olves

0

如果你只想性能與同類型的參數匹配,這種擴展方法可以幫助,

public static class ListExtensions 
{ 
    public static IEnumerable<T> MatchWithAnyProperty<T, TK>(this IEnumerable<T> list, TK value) 
    { 
     var argType = typeof (TK); 
     var properties = typeof(T).GetProperties().Where(x => x.PropertyType.IsAssignableFrom(argType)); 

     return list.Where(item => properties.Any(prop => 
      { 
       var propertyValue = prop.GetValue(item, null); 
       if (value == null) 
        return propertyValue == null; 
       return propertyValue.Equals(value); 
      })); 
    } 
} 

這可以像使用,

var items = new[] 
      { 
       new 
        { 
         Name = "Test", 
         Age = 20, 
         Test=25 
        }, 
       new 
        { 
         Name = "Hello", 
         Age = 10, 
         Test=15 
        }, 
       new 
        { 
         Name = "T2gdhest", 
         Age = 14, 
         Test=20 
        }, 
       new 
        { 
         Name = "hai", 
         Age = 33, 
         Test=10 
        }, 
       new 
        { 
         Name = "why not", 
         Age = 10, 
         Test=33 
        }, 
      }; 

     var match= items.MatchWithAnyProperty(10); 

     foreach (var item in match) 
     { 
      Console.WriteLine(item.Name); 
     } 
     Console.ReadKey(); 
+0

Mathew, 我試過這個,它的工作原理與廣告一樣,除非屬性值爲null。 – w2olves

0

而且有舊的方式...

public static IList<T> MyMethod<T>(IList<T> myList, string filter) 
    { 
     if (myList == null) return null; 
     if (filter == null) return myList; 

     var tfilter = filter.GetType(); 
     var properties = typeof(T).GetProperties().Where(x => x.PropertyType.FullName == typeof(string).FullName); 
     if (!properties.Any()) return null; 


     var res = new List<T>(); 

     foreach(var el in myList) 
     { 
      foreach(var p in properties) 
      { 
       if ((string)p.GetValue(el) == filter) 
       { 
        res.Add(el); 
        break; 
       } 
      } 
     } 
     return res; 
    }