private IQueryable<Customer> FilterResult(string search, List<Customer> dtResult, List<string> columnFilters)
{
IQueryable<Customer> results = dtResult.AsQueryable();
results = results.Where(p =>
(
search == null ||
(
p.Name != null && p.Name.ToLower().Contains(search.ToLower())
|| p.City != null && p.City.ToLower().Contains(search.ToLower())
|| p.Postal != null && p.Postal.ToLower().Contains(search.ToLower())
|| p.Email != null && p.Email.ToLower().Contains(search.ToLower())
|| p.Company != null && p.Company.ToLower().Contains(search.ToLower())
|| p.Account != null && p.Account.ToLower().Contains(search.ToLower())
|| p.CreditCard != null && p.CreditCard.ToLower().Contains(search.ToLower())
)
)
&& (columnFilters[0] == null || (p.Name != null && p.Name.ToLower().Contains(columnFilters[0].ToLower())))
&& (columnFilters[1] == null || (p.City != null && p.City.ToLower().Contains(columnFilters[1].ToLower())))
&& (columnFilters[2] == null || (p.Postal != null && p.Postal.ToLower().Contains(columnFilters[2].ToLower())))
&& (columnFilters[3] == null || (p.Email != null && p.Email.ToLower().Contains(columnFilters[3].ToLower())))
&& (columnFilters[4] == null || (p.Company != null && p.Company.ToLower().Contains(columnFilters[4].ToLower())))
&& (columnFilters[5] == null || (p.Account != null && p.Account.ToLower().Contains(columnFilters[5].ToLower())))
&& (columnFilters[6] == null || (p.CreditCard != null && p.CreditCard.ToLower().Contains(columnFilters[6].ToLower())))
);
return results;
}
这是我用于数据表过滤器的方法,我的问题是我可以将其作为通用吗?我觉得它可以使用反射。但这对性能有影响吗?
事先提前......到目前为止我已经做到了:
private IQueryable<T> FilterResult<T>(string search, IQueryable<T> dtResult, List<string> columnFilters)
{
IQueryable<T> results = dtResult;
Type typeParameterType = typeof(T); // this will give me the class detail which I have passed
// 1 How to extract all property of this class to use in where clause
// 2 How I can use it either dynamic linq , foreach or any possible solution.
//1
PropertyInfo[] properties = typeParameterType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var item in properties)
{
// This will be changed after some validation logic
string predicate = item.Name + " = " + search;
results = results.Where(predicate);
}
return results;
}
答案 0 :(得分:1)
我不熟悉(并且不打算使用)动态LINQ。在这种情况下,你真的不需要这样的东西。正如我所说,我不会将字符串列表作为列过滤器传递,它会使代码更长,顺序可能很重要并导致难以调试的问题。这是我刚刚提出的代码,您可以尝试,但我不确定它是否有效,但如果有的话请告诉我:
private IEnumerable<T> FilterResult<T>(string search, IQueryable<T> dtResult, params ColumnFilter<T>[] filters)
{
var propGetters = typeof(T).GetProperties().Where(p => p.PropertyType == typeof(string))
.Select(p => new Func<object,string>((item) => ((p.GetValue(item, null) as string) ?? "").ToLower())).ToList();
if(!string.IsNullOrEmpty(search)) {
Func<T,bool> predicate = e => propGetters.Aggregate(false, (c,o) => c || o(e));
dtResult = dtResult.Where(predicate).AsQueryable();
}
return filters.Aggregate(dtResult.AsEnumerable(), (c,e) => c.Where(o => e.IsOK(o));
}
public class ColumnFilter<T> {
public ColumnFilter(Func<T,string> selector, string term = ""){
PropertySelector = selector;
Term = term;
}
public Func<T,string> PropertySelector {get;set;}
public string Term {get;set;}
public bool IsOK(T item) {
return PropertySelector(item).Contains(Term);
}
}
<强>用法强>:
FilterResult(yourSearch, yourDtResult, new ColumnFilter(e=>e.City, "someCitySearch"),
new ColumnFilter(e=>e.Postal, "somePostalSearch"), ...);
如果您仍想坚持columnFilters
的列表,可以修改代码,但肯定会更长。