2017-05-30 5 views
0

私はその後、私は各クラスに検索機能を追加する必要がある2つのクラスWeb APIが2つのクラスを超えていますか?

public class C1 : ApiController { ... 
    public List<C1> GetAll() { ....} // GetAll(string search = null) 
} 

public class C2 : ApiController { ... 
    public List<C2> GetAll() { ....} // GetAll(string search = null). 
} 

を持っています。そこで、それぞれGetAll()に検索パラメータを追加しました。GetAll(string search = null)です。 searchがnullの場合、メソッドはすべてのリストを返します。そうでなければ、フィルタリングされた結果リストを返します。

今私はC1C2のデータベーステーブルで検索しC1C2SearchC1AndC2ViewModel)の二つのリストを返す検索機能を追加する必要があります。どこで機能を実装すればよいですか?あるいは、私はこのクラスのためだけに新しいクラスを作成すべきですか?

public class SearchC1AndC2ViewModel { 
    public List<C1> C1s; 
    public List<C2> C2s; 
} 

のWeb APIは、すべての

public SearchC1AndC2ViewModel Search(string search) 

答えて

0

ファーストを実装するために、私は今それがあなたのコントローラと同じように表示されるあなたは、検索とGETALL方法で型パラメータを悪用してきたと仮定します。

一般的なソリューションを共有するための仕組みを探しているようです。 あなたがしようとしていることを達成するには複数の方法があります。

オプション1:基本コントローラクラス

は、これら二つのコントローラの基本クラスを定義し、そこでの一般的な検索方法を実装します。コントローラにデータアクセスロジックを置くことは理想的ではないので、おそらくロジックを別の場所に移動してここから呼び出すだけです。ここでのコードは、その場合にはどのように見えるかです:

public abstract class CustomControllerBase<T> : ApiController 
{ 
    public List<T> GetAll(string filter = null) 
    { 
     // Common code goes here. 
     // At some point you may need some customization based on the actual implementation 
     return this.RetrieveRecords(filter); 
    } 

    protected abstract List<T> RetrieveRecords(string filter); 
} 

public class Controller1 : CustomControllerBase <C1> 
{ 
    protected override List<C1> RetrieveRecords (string filter) { 
     // Custom logic goes here 
    } 
} 

public class Controller2 : CustomControllerBase <C2> 
{ 
    protected override List<C2> RetrieveRecords (string filter) { 
     // Custom logic goes here 
    } 
} 

オプション2:委任データ層

に2つ目のオプションは、データアクセス操作のための専用のクラスを持って、それが一般的なようにすることです複数のタイプに再利用することができます。データベース(または他のデータストア)から取得しようとしている2つのエンティティの唯一の違いが、エンティティのタイプとソース(テーブル名)である場合、データクラスのコンストラクタのパラメータを作成できます。

public class DataAccessHandler<T> 
{ 
    private Func<QueryResultItem, T> queryResultProcessingLogic; 

    public DataAccessHandler(Func<QueryResultItem, T> queryResultProcessingLogic) 
    { 
     // Validation goes here 
     this.queryResultProcessingLogic = queryResultProcessingLogic; 
    } 

    public List<T> Retrieve(string filter = null) 
    { 
     QueryResult queryResult = // Retrieve query results given query. this is your custom implementation. QueryResult type is an abstraction, you'll have to replace it with the actual type you use. I'm sharing just the concept here. 
     return queryResult.Select(item=>queryResultProcessingLogic(item)).ToList(); 
    } 
} 

public class Controller1 : ApiController 
{ 
    private readonly DataAccessHandler<C1> dataHandler; 

    public Controller1 (DataAccessHandler<C1> dataHandler) 
    { 
     // Validate arguments here 

     this.dataHandler = dataHandler; 
    } 

    public List<C1> GetAll(string filter) 
    { 
     return this.dataHandler.GetAll(filter); 
    } 
} 

最善のアプローチは、両方のオプション:)このことができます

希望を組み合わせることであろう。

+1

'CustomControllerBase'は、抽象メソッドを持たせるために抽象でなければなりません。 –

+0

良いキャッチ、更新。ありがとうマルコ。 – Artak

0

問題がその関数の戻り値の型だけのクラスを作成している場合は、Tuple<List<C1>, List<C2>>を返すことができます。


今、あなたは新しいコントローラに他のコントローラからGetAllメソッドを再利用するために探しているなら、そのクラス組成に歓迎! C1コントローラーとC2コントローラーの両方を継承するコントローラーは、クラスが複数のクラスから継承できないため、コントローラーを作成することはできません。代わりに空のインターフェイスを作成してGetAllメソッドで拡張する必要がありますが、両方のインターフェイスから継承するので、GetAllへの呼び出しが曖昧になるためメソッドが衝突します。そのため、メソッド名も変更する必要があります。しかし、C1C2は、実際にはApiControllerから継承するクラスであり、インターフェイスはクラスから継承できないため、インターフェイスを作成してC1C2の両方を継承し、ApiControllerとする必要があります。私は誰がこれを発明したのか分かりませんが、実際にはそれを行うための「適切な」方法です。それは混乱です。ここに私達は行く:

// First define the interfaces 
public interface IC1 { } 
public interface IC2 { } 

// Then extend the with the GetAll methods 
public static class ICExtensions 
{ 
    public static List<C1> GetAllC1(this IC1, string search = null) { ... } 
    public static List<C2> GetAllC2(this IC2, string search = null) { ... } 
} 

// These are now your controllers 
public class C1Controller : ApiController, IC1 { ... } 
public class C2Controller : ApiController, IC2 { ... } 

// And here is the new controller that has the two GetAll methods 
public class C1AndC2Controller : ApiController, IC1, IC2 { ... } 

今、あなたは自由にあなたはそれが好きな新しいクラス、Tupleを返すことができ、C1AndC2ControllerGetAllメソッドを実装することができます。