如何使给定的方法通用?在性能方面使它具有通用性是一个好主意吗?

时间:2015-09-19 09:14:00

标签: performance entity-framework linq c#-4.0

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;
    }

1 个答案:

答案 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的列表,可以修改代码,但肯定会更长。