2015-02-02 2 views
1

Я пытаюсь создать функцию поиска для списка. Это довольно просто, однако я пытаюсь использовать метод, который может принимать списки разных типов. Возьмите следующий пример, чтобы уяснить вопрос:Использовать общий метод со списком другого типа/класса

Методы SearchGridViewCategorie и SearchGridViewMedewerker - это методы поиска в Списке, если он содержит поисковый запрос.

public static void SearchGridViewMedewerker(ref List<Medewerker> medewerkers, String term) { 
    medewerkers = medewerkers.Where(m => m.gebruikersnaam.ToLower().Contains(term.ToLower()) || 
        m.naam.ToLower().Contains(term.ToLower()) || 
        m.email.ToLower().Contains(term.ToLower()) || 
        m.rol.ToLower().Contains(term.ToLower())).ToList(); 
} 

public static void SearchGridViewCategorie(ref List<Categorie> categorieen, String term) { 
    categorieen = categorieen.Where(c => c.omschrijving.ToLower().Contains(term.ToLower())).ToList(); 
} 

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

public static List<object> SearchGridView(List<object> list, String term) { 
    IList<PropertyInfo> properties = list.GetType().GetProperties().ToList(); 
    List<object> tempList = new List<object>(); 

     foreach(object o in list){ 
      foreach (var property in properties) { 
       if (property.ToString().Contains(term.ToLower())) { 
        tempList.Add(o); 
       } 
      } 
     } 
    return tempList; 
} 

Однако с этим решением я должен преобразовать список типа T в список объектов до передачи списка в методе.

Это не то, что я хочу. Я хочу передать список любого типа, обработать его и вернуть список типа, заданного в качестве параметра. Это возможно?

+0

Вы понимаете, что 'property.ToString()' просто возвращает «System.Reflection.PropertyInfo» каждый раз, да? – samjudson

+1

Использование 'List ' немного отличается от использования массива. Вместо этого вы должны изменить метод для принятия аргументов типа. Многие из них обсуждаются в [Введение в C# Generics в MSDN] (https://msdn.microsoft.com/en-us/library/ms379564 (v = vs.80) .aspx). – mason

+0

@samjudson Ах, да, я плохой, но вы поняли, что я пытаюсь выполнить. – Sliver2009

ответ

2

Я думаю, что это то, что вы имеете в виду:

public static IList<T> SearchGridView<T>(IList<T> list, String term) 
{ 
    IList<PropertyInfo> properties = typeof(T).GetProperties(); 
    var t = term.ToLower(); 
    return list 
     .Where(item => 
      properties 
       .Select(p => p.GetValue(item).ToString()) 
       .Any(v => v.Contains(t))) 
     .ToList(); 
} 
+0

Спасибо, это именно то, что я считаю. В чем разница между IList и List? Кажется, работает с обоими !? – Sliver2009

+2

'IList ' это интерфейс, который 'List ' реализует. Массивы также реализуют 'IList ', поэтому он обеспечивает большую гибкость. Если бы я писал этот метод, я бы сделал его как можно более общим, заменив 'IList ' на 'IEnumerable ' и сбросив' .ToList() '. – spender

+1

Возможно, стоит отметить, что часть выражения 'v.Contains (t)' выражения LINQ выполняет зависящее от регистра соответствие для текста поиска. Что бы вы могли захотеть сделать, это изменить часть 'Select' выражения, чтобы ввести значение свойства, например:' .Select (p => p.GetValue (item) .ToString(). ToLower()) ', тогда поиск будет игнорировать корпус. –

1

Похоже, что вы пытаетесь упростить код этой природы:

x => x.property.ToLower().Contains(term.ToLower()) 

где свойство является свойством строки и термин - это текст, который вы хотите найти. Если да, то вы можете использовать метод расширения LINQ, чтобы сделать это:

public static class Extensions 
{ 
    public static IEnumerable<T> WhereTextInProperties<T>(this IEnumerable<T> source, 
     string searchText, params Func<T, string>[] getPropertyValues) 
    { 
     searchText = searchText.ToLowerInvariant(); 

     return from element in source 
       from getPropertyValue in getPropertyValues 
       let propertyValue = getPropertyValue(element) 
       where propertyValue.ToLowerInvariant().Contains(searchText) 
       select element; 
    } 
} 

Тогда вы бы использовать его как это:

return medewerkers.WhereTextInProperties(term, 
    m => m.gebruikersnaam, m => m.naam, 
    m => m.email, m => m.rol 
    ); 

Вы могли бы улучшить это различными способами (Regex, список выражения вместо делегатов функций и т. д.), но это может послужить отправной точкой.

Смежные вопросы