使用具有不同 type/class 列表的通用方法
Use a generic method with a list of different type/class
我正在尝试为列表构建搜索功能。这很简单,但是我正在尝试一种方法,它可以采用不同类型的列表。拿下面的例子来澄清这个问题:
方法 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 的列表转换为对象列表,然后再将列表传递到方法中。
那不是我想要的。我想传递一个任何类型的列表,对其进行处理,然后 return 一个已作为参数给出的类型的列表。这可能吗?
我认为这就是你的意思:
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();
}
看起来您正在尝试简化这种性质的代码:
x => x.property.ToLower().Contains(term.ToLower())
其中 属性 是一个字符串 属性 而 term 是您要搜索的文本。如果是这样,您可以使用 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
);
您可以通过各种不同的方式(正则表达式、表达式列表而不是函数委托等)改进它,但它可能会作为一个起点。
我正在尝试为列表构建搜索功能。这很简单,但是我正在尝试一种方法,它可以采用不同类型的列表。拿下面的例子来澄清这个问题:
方法 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 的列表转换为对象列表,然后再将列表传递到方法中。
那不是我想要的。我想传递一个任何类型的列表,对其进行处理,然后 return 一个已作为参数给出的类型的列表。这可能吗?
我认为这就是你的意思:
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();
}
看起来您正在尝试简化这种性质的代码:
x => x.property.ToLower().Contains(term.ToLower())
其中 属性 是一个字符串 属性 而 term 是您要搜索的文本。如果是这样,您可以使用 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
);
您可以通过各种不同的方式(正则表达式、表达式列表而不是函数委托等)改进它,但它可能会作为一个起点。