[英]Combining two extension methods into one
我有這個擴展方法:
public static IQueryable<T> FilterByEmployee<T>(this IQueryable<T> source, EmployeeFilter filter)
where T : class, IFilterableByEmployee
{
if (!string.IsNullOrEmpty(filter.Gender))
source = source.Where(e => e.Employee.Gender == filter.Gender);
if (!string.IsNullOrEmpty(filter.NationalityID))
source = source.Where(e => e.Employee.NationalityID == filter.NationalityID);
// filter the group
if (filter.IncludeChildGroups)
{
var groups = Security.GetAllChildGroups(filter.GroupID);
source = source.Where(e => e.Employee.EmployeeGroupID.HasValue
&& groups.Contains(e.Employee.EmployeeGroupID.Value));
}
else
{
source = source.Where(e => e.Employee.EmployeeGroupID == filter.GroupID);
}
// filter status
if (filter.OnlyActiveEmployees)
source = source.Where(e => e.Employee.Status == "Active");
return source;
}
另一個完全相同,但是它直接過濾Employees
上下文:
public static IQueryable<T> Filter<T>(this IQueryable<T> source, EmployeeFilter filter)
where T : Employee
{
if (!string.IsNullOrEmpty(filter.Gender))
source = source.Where(e => e.Gender == filter.Gender);
if (!string.IsNullOrEmpty(filter.NationalityID))
source = source.Where(e => e.NationalityID == filter.NationalityID);
// filter the group
if (filter.IncludeChildGroups)
{
var groups = Security.GetAllChildGroups(filter.GroupID);
source = source.Where(e => e.EmployeeGroupID.HasValue
&& groups.Contains(e.EmployeeGroupID.Value));
}
else
{
source = source.Where(e => e.EmployeeGroupID == filter.GroupID);
}
// filter status
if (filter.OnlyActiveEmployees)
source = source.Where(e => e.Status == "Active");
return source;
}
我討厭兩次擁有幾乎相同的代碼的想法,如何將這兩種方法合而為一? (如果可能的話),或者至少使其成為兩種方法,但其中一種進行過濾? 原始代碼更長,這也是原因之一。
您可以直接和明確地在Employee
上實現IFilterByEmployee
:
public class Employee : IFilterByEmployee
{
Employee IFilterByEmployee.Employee
{
get { return this; }
}
}
通過顯式實現接口,它實際上使它成為一種“達到目的”的解決方案。
編輯:這可能不適用於LinqToEf。 直接編寫SQL存在相同的問題。 查詢的上下文在這里很關鍵,因此很難以LinqToEf可以智能(或神奇地)正確地解釋它的方式來抽象查詢。
LINQKit應該可以實現:
public static IQueryable<T> Filter<T>(this IQueryable<T> source, Expression<Func<T, Employee>> employeeSelector, EmployeeFilter filter)
{
source = source.AsExpandable();
if (!string.IsNullOrEmpty(filter.Gender))
source = source.Where(e => employeeSelector.Compile().Invoke(e).Gender == filter.Gender);
if (!string.IsNullOrEmpty(filter.NationalityID))
source = source.Where(e => employeeSelector.Compile().Invoke(e).NationalityID == filter.NationalityID);
// filter the group
if (filter.IncludeChildGroups)
{
var groups = Security.GetAllChildGroups(filter.GroupID);
source = source.Where(e => employeeSelector.Compile().Invoke(e).EmployeeGroupID.HasValue
&& groups.Contains(employeeSelector.Compile().Invoke(e).EmployeeGroupID.Value));
}
else
{
source = source.Where(e => employeeSelector.Compile().Invoke(e).EmployeeGroupID == filter.GroupID);
}
// filter status
if (filter.OnlyActiveEmployees)
source = source.Where(e => employeeSelector.Compile().Invoke(e).Status == "Active");
return source;
}
source = source.AsExpandable();
在EF查詢周圍創建一個包裝器,以確保employeeSelector.Compile().Invoke(e)
得到適當的翻譯,盡管看起來很象,但它實際上沒有編譯任何表達式樹,並且EF應該只看到它實際支持的表達式。
如果直接在雇員上進行過濾,則可以使用e => e
作為雇員選擇器,否則,可以使用e => e
e => e.Employee
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.