2016-10-03 7 views
0

スパゲッティコードを回復しました。リファクタリングする必要があります。私は200行以上のメソッドを望んでいません。私にとってはオブジェクト指向プログラミングではありません。私はその質問に熟考しようとしています、私はあなたの提案をしたいと思います。IQueryableのWHERE節をファクタリング

これは私のコードです:

ライン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); 
} 

ライン237

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

これは良い質問です:http://codereview.stackexchange.com –

+1

オブジェクトプログラミングかどうか、これは動的フィルタを構築する正しい方法です。通常のメソッドリファクタリングの場合と同様に、Bigメソッドの一部を独自のメソッドに取り出すことができますが、Wh​​ereとIQueryableは共通していません。 –

+3

行数が問題になる場合は、{if}条件から '{}'大括弧を削除すると、条件ごとに2行減ります:) –

答えて

2

この1つは私にはやり過ぎのようです(私はそれがコメントで表示された多型だと思う)、とにかく、そこにそれがある:

我々はインターフェイスを起動します。

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

美しい、感謝:)一部の人々は恣意的にdownvote – 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