将两种扩展方法合二为一

Nea*_*hal 6 c# extension-methods linq-to-entities entity-framework

我有这个扩展方法:

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;
    }
Run Code Online (Sandbox Code Playgroud)

和另一个完全相同,但它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;
    }
Run Code Online (Sandbox Code Playgroud)

我讨厌两次使用几乎相同的代码的想法,如何将这两种方法合并为一种?(如果可能的话)或者至少使它成为两种方法,但在其中一种方法中进行过滤?原始代码更长,这也是其中一个原因.

Ed *_*pel 0

您可以直接明确地IFilterByEmployee实现:Employee

public class Employee : IFilterByEmployee
{
    Employee IFilterByEmployee.Employee
    {
        get { return this; }
    }
}
Run Code Online (Sandbox Code Playgroud)

通过显式实现接口,它本质上使其成为一种“达到目的的手段”的解决方案。

编辑:这可能不适用于 LinqToEf。直接写SQL也有同样的问题。查询的上下文在这里至关重要,因此很难以 LinqToEf 能够智能(或神奇地)正确解释它的方式对其进行抽象。