2013-12-13 3 views
1

Я новичок в Reflection, поэтому, пожалуйста, извините мой вопрос о noob. Как создать метод, который принимает два параметра, общий список и строку, а затем находит все элементы в этом списке, где любое значение свойства соответствует строке.Отражение на список фильтров <T>

Так, например, у нас есть объект с 3 свойствами, я передаю список этого объекта методу и строке поиска и возвращает обратно список объектов, в которых любое из свойств может содержать строку поиска.

Я могу сделать так:

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

Но как я могу сделать этот метод Generic так что я могу передать любой список объектов для него?

Заранее спасибо ...

+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

Awesome, как можно расширить это, чтобы расширение .Contains? Итак, вместо 100% соответствия я могу просто открыть объекты, содержащие строку? – w2olves

+0

Просто измените «{0} == @ 0" на "{0} .Contains (@ 0)", но вы должны проверить значение null, поэтому, если некоторые свойства могут быть пустыми, используйте "{0}! = Null && { 0} .Contains (@ 0)» – pil0t

1

Используйте Type.GetProperties(), чтобы получить все свойства объекта. Используйте PropertyInfo.GetValue(), чтобы получить значение данного свойства в заданном объекте. Вам нужно выяснить, как вы хотите совместить свою строку с DateTime, с числами или с другими сложными объектами. Поместите все это в функцию, например, 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 имеет значение null? – w2olves

+0

Хорошая точка, и хорошо заметили, но это пример кода, показывающий концепцию, а не готовый к производству код. Конечно, вы тоже можете легко проверить нуль. Благодарим за указание. –

+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; 
    } 
Смежные вопросы