2016-10-03 46 views
0

我恢复了一些意大利面代码,我不得不重构它。我不想要一个超过200行的方法,对我来说,它不是面向对象的编程。我正在努力思考这个问题,我想提出你的建议。保留IQueryable中的WHERE子句

这是我的代码:

线237 18

if (searchCriteria.EventReference != null) 
{ 
    query = query.Search(x = > x.EventReference, searchCriteria.EventReference); 
} 
if (searchCriteria.PendingEvent == false) 
{ 
    query = query.Where(x = > x.EventStatusId != EventStatus.Pending); 
} 
if (searchCriteria.VerifiedEvent == false) 
{ 
    query = query.Where(x = > x.EventStatusId != EventStatus.Verified); 
} 
if (searchCriteria.CanceledEvent == false) 
{ 
    query = query.Where(x = > x.EventStatusId != EventStatus.Canceled); 
} 

线

if (searchCriteria.RemitterId != null) 
{ 
    query = query.Where(x = > x.Trade.RemitterId == searchCriteria.RemitterId); 
} 
+1

这是一个很好的问题:http://codereview.stackexchange.com –

+1

对象编程与否,这是构建动态过滤器的正确方法。您可以随时将大方法的某些部分提取到自己的方法中,就像任何常规方法重构一样,“Where”和“IQueryable”没有什么共同之处。 –

+3

如果你想关注的行数,然后从'if'条件中删除'{}'括号,你会减少两条线,每个条件:) –

回答

2

这一次似乎是矫枉过正,我(但我想这是出现在评论多态性),但无论如何, ,还有它是:

我们先从一个接口:

public interface IQueryFilter 
{ 
    IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria); 
} 

然后实现共同财产:

public abstract class AQueryFilter<T> : IQueryFilter 
{ 
    public AQueryFilter(Func<SearchCriteria, T> criteria) 
    { 
     Criteria = criteria; 
    } 

    protected Func<SearchCriteria, T> Criteria { get; } 
    public abstract IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria); 
} 

最后,所有具体的东西:

public class WhereEventStatusQueryFilter : AQueryFilter<bool> 
{ 
    private EventStatus _toTest; 

    public WhereEventStatusQueryFilter(Func<SearchCriteria, bool> criteria, EventStatus toTest) 
     : base(criteria) 
    { 
     _toTest = toTest; 
    } 

    public override IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria) 
    { 
     return (Criteria(searchCriteria) ? query : query.Where(x => x.EventStatusId != _toTest)); 
    } 
} 

public class SearchQueryFilter : AQueryFilter<object> 
{ 
    Func<Whatever, object> _searchFor; 

    public SearchQueryFilter(Func<SearchCriteria, object> criteria, Func<Whatever, object> searchFor) 
     : base(criteria) 
    { 
     _searchFor = searchFor; 
    } 

    public override IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria) 
    { 
     return (Criteria(searchCriteria) == null ? query : query.Search(x => _searchFor(x), Criteria(searchCriteria))); 
    } 
} 

public class WhereEqualQueryFilter : AQueryFilter<object> 
{ 
    Func<Whatever, object> _searchFor; 

    public WhereEqualQueryFilter(Func<SearchCriteria, object> criteria, Func<Whatever, object> searchFor) 
     : base(criteria) 
    { 
     _searchFor = searchFor; 
    } 

    public override IQueryable<Whatever> Filter(IQueryable<Whatever> query, SearchCriteria searchCriteria) 
    { 
     return (Criteria(searchCriteria) == null ? query : query.Where(x => _searchFor(x) == Criteria(searchCriteria))); 
    } 
} 

用法:

var filters = new IQueryFilter[] 
{ 
    new WhereEventStatusQueryFilter(x => x.PendingEvent, EventStatus.Pending), 
    new WhereEventStatusQueryFilter(x => x.VerifiedEvent, EventStatus.Verified), 
    new SearchQueryFilter(x => x.EventReference, x => x.EventReference), 
    new WhereEqualQueryFilter(x => x.RemittedId, x => x.Trade.RemittedId), 
    ... 
}; 

foreach (var filter in filters) 
    query = filter.Filter(query, searchCriteria); 

但这种方法隐藏了很多的逻辑。如果有人想添加一些内容,他必须阅读所有以前的过滤器类,以了解是否已有可以完成工作或者必须编写另一个过滤器的类。

+0

美丽,谢谢:)。有些人任意倒下 – Coding4Fun

1

嗯,我不认为这真是再好不过了,但你可以做这样的事情:

var searchDict = new Dictionary<Func<bool>, Func<IQueryable<?>>>() 
{ 
    {() => searchCriteria.EventReference != null, query.Search(x = > x.EventReference, searchCriteria.EventReference) }, 
    {() => searchCriteria.VerifiedEvent == false, query.Where(x = > x.EventStatusId != EventStatus.Verified) }, 
    {() => searchCriteria.RemitterId != null, query.Where(x = > x.Trade.RemitterId == searchCriteria.RemitterId) }, 
    ... 
}; 

foreach (var item in seachDict) 
    if (item.First()) 
     query = item.Second(); 

或(取决于你想在哪里以及如何建立你的词典):

var searchDict = new Dictionary<Func<SearchCriteria, bool>, Func<IQueryable<?>, IQueryable<?>>>() 
{ 
    { c => c.EventReference != null, q => q.Search(x = > x.EventReference, searchCriteria.EventReference)}, 
    { c => c.VerifiedEvent == false, q => q.Where(x = > x.EventStatusId != EventStatus.Verified) }, 
    { c => c.RemitterId != null, q => q.Where(x = > x.Trade.RemitterId == searchCriteria.RemitterId) }, 
    ... 
}; 

foreach (var item in seachDict) 
    if (item.First(searchCriteria)) 
     query = item.Second(query); 
+0

字典是一个好主意,为什么不。但我想要对象编程。但你的想法不坏 – Coding4Fun

+1

谢谢:)如果没有人用对象回答,我会在后面提出另一种解决方案。 –

+0

不错,从你:) – Coding4Fun