2012-01-26 6 views
0

誰かが私をより良いプログラマにする手助けをしたいですか?データフィルタリングコードで再利用性が改善される

私はさまざまな基準でオブジェクトのコレクションをフィルタリングするアプリケーションを持っています。現在、私のコードは動作しますが、90%が重複しています。私は何か間違っていると感じています。より再利用可能なフィルタリングコードを作成する方法に関する提案はありますか?

私はこのようなオブジェクトのコレクションを持っていると仮定すると:

public class ExampleData 
{ 
    public int SomeValue1 { get; set; } 
    public int SomeValue2 { get; set; } 
    public int SomeValue3 { get; set; } 
    public string SomeValue4 { get; set; } 
} 

そして、ここでは私のフィルタクラスです。コードコメントを見てください。

class ExampleFilter 
{ 
    public ExampleFilter() 
    { 
    } 

    public IEnumerable<ExampleData> applyFilters(SearchCriteria criteria, IEnumerable<ExampleData> data) 
    { 
     //The body of these methods is almost identical...how can I better design this process so I don't cut and paste 90% of the code? 
     data = filterByValue1Selections(criteria.FormTemplateSelected, data); 
     data = filterByValue2Selections(criteria.FormTemplateSelected, data); 
     return data; 
    } 

    public IEnumerable<ExampleData> filterByValue1Selections(List<int> value1Ids, IEnumerable<ExampleData> data) 
    { 
     if (value1Ids != null) 
     { 
      IEnumerable<ExampleData> dataQuery = null; 
      foreach (int selectedValueIds in value1Ids) 
      { 
       //See http://justgeeks.blogspot.com/2011/01/using-linq-in-foreach-loop-to-build.html 
       //For explanation of why we copy this locally 
       int selectedId = selectedValueIds; 
       if (dataQuery == null) 
       { 
        //This code and the similar block in the else are the only differences in these methods 
        dataQuery = data.Where(t => t.SomeValue1 == selectedId); 
       } 
       else 
       { 
        dataQuery = dataQuery.Union(data.Where(t => t.SomeValue1 == selectedId)); 
       } 
      } 
      data = dataQuery; 
     } 
     return data; 
    } 

    public IEnumerable<ExampleData> filterByValue2Selections(List<int> value2Ids, IEnumerable<ExampleData> data) 
    { 
     if (value2Ids != null) 
     { 
      IEnumerable<ExampleData> dataQuery = null; 
      foreach (int selectedValueIds in value2Ids) 
      { 
       //See http://justgeeks.blogspot.com/2011/01/using-linq-in-foreach-loop-to-build.html 
       //For explanation of why we copy this locally 
       int selectedId = selectedValueIds; 
       if (dataQuery == null) 
       { 
        dataQuery = data.Where(t => t.SomeValue1 == selectedId); 
       } 
       else 
       { 
        dataQuery = dataQuery.Union(data.Where(t => t.SomeValue1 == selectedId)); 
       } 
      } 
      data = dataQuery; 
     } 
     return data; 
    } 


} 

答えて

2

あなたは基本的にContains()メソッドを再実装している - あなただけ行うことができます。

List<int> valueIds = ...; 
var filteredData = data.Where(x=> valueIds.Contains(x.SomeValue1)); 

その後、あなたのapplyFilters方法は、次のようになります。一般的には

public IEnumerable<ExampleData> applyFilters(SearchCriteria criteria, IEnumerable<ExampleData> data) 
{ 
    data = data.Where(x=> criteria.FormTemplateSelected.Contains(x.SomeValue1) 
         && criteria.FormTemplateSelected.Contains(x.SomeValue2)); 
    return data; 
} 
+0

私はそれが何か簡単だろうとわかった。今私はちょっとばかばかしい感じがするが、少なくとも私は答えがある。 – Amasuriel

1

をあなたが作ることができます繰り返されるFilterByValueメソッドを一般化するためにFunc<T, TResult> delegatesを使用すると、次のようなものを試すことができます(擬似コード):

public IEnumerable<T> FilterByValue<T>(List<int> value1Ids, IEnumerable<T> data, Func<T, int> selector) 
{ 
    if (value1Ids != null) 
    { 
     IEnumerable<ExampleData> dataQuery = null; 
     foreach (int id in value1Ids) 
     { 
      int selectedId = id; 
      if (dataQuery == null) 
      { 
       dataQuery = data.Where(x => selector(x) == id); 
      } 
      else 
      { 
       dataQuery = dataQuery.Union(data.Where(x => selector(x) == id)); 
      } 
     } 

     data = dataQuery; 
    } 

    return data; 
} 

あなたが実際のプロパティの選択を渡すことができますこの方法は:

FilterByValue(criteria.FormTemplateSelected, data, x => SomeValue1); 
FilterByValue(criteria.FormTemplateSelected, data, x => SomeValue2); 

シナリオに応じてあなたはさらに行くと、デリゲートに、より複雑なロジックを適用するが、それは、コードからあなたを判断するのは難しいことができます」あなたが最も関心のある部分を貼り付けました。

関連する問題