2017-05-30 45 views
0

我有兩個類Web api跨兩個類?

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爲空,方法將返回所有列表;否則,它將返回過濾結果列表。現在

我需要補充的是在搜索的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:委派到數據層

第二個選項是針對數據訪問操作的專用類,並使它通用,所以它可以重複使用多種類型。如果您試圖從數據庫(或其他數據存儲區)檢索的那兩個實體之間唯一的區別是實體類型和源(表名稱),那麼可以創建數據類構造函數的這些參數。

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

良好的漁獲,更新抽象。感謝Marco。 – Artak

0

如果問題是隻爲該函數的返回類型創建一個類,那麼您可以讓它返回一個Tuple<List<C1>, List<C2>>


現在,如果你正在尋找來自其他控制器的GetAll方法重用到一個新的控制器,然後歡迎階級成分!由於一個類不能從多個類繼承,因此無法構建繼承自C1控制器和C2控制器的控制器。相反,你必須做出一個空的接口,並與GetAll方法擴展它,但你會從兩個接口繼承的方法將發生碰撞,以GetAll的調用將變得模糊,所以你也必須改變方法名。但C1C2實際上是從ApiController繼承的類和接口不能從一個類繼承,所以你將不得不作出的接口,無論是從他們和ApiController使C1C2繼承。我不知道是誰發明了這一點,但它實際上是「正確」的方式做到這一點,並它是一個爛攤子。在這裏,我們去:

// 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 { ... } 

現在,你可以自由地實現C1AndC2ControllerGetAll方法,它可以返回一個新的類,Tuple,不管你想要它。