2016-10-03 64 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