2011-07-08 39 views
26

說我對暴露分頁列表如下界面模式的揭露通用接口的非通用版本

public interface IPagedList<T> 
{ 
    IEnumerable<T> PageResults { get; } 
    int CurrentPageIndex { get; } 
    int TotalRecordCount { get; } 
    int TotalPageCount { get; }   
    int PageSize { get; } 
} 

現在我想建立一個呼叫控制

public class PagedListPager<T> 
{ 
    public PagedListPager<T>(IPagedList<T> list) 
    { 
     _list = list; 
    } 

    public void RenderPager() 
    { 
     for (int i = 1; i < list.TotalPageCount; i++) 
      RenderLink(i); 
    } 
} 

尋呼控制有對T(列表的實際內容)沒有興趣。它只需要頁面數量,當前頁面等。所以PagedListPager是通用的唯一原因是,它將與通用IPagedList<T>參數進行編譯。

這是代碼味道嗎?我應該關心我是否有效地使用冗餘通用?

在這種情況下是否有一個標準模式用於公開接口的其他非通用版本,因此我可以刪除尋呼機上的泛型類型?

public class PagedListPager(IPagedList list) 

編輯

我想我也想補充我已經解決了這個問題,目前的方式,並邀請它是否是一個合適的解決方案評論:

public interface IPagedList // non-generic version 
{ 
    IEnumerable<object> PageResults { get; } 
    int CurrentPageIndex { get; } 
    int TotalRecordCount { get; } 
    int TotalPageCount { get; }   
    int PageSize { get; } 
} 


public class ConcretePagedList<T> : IPagedList<T>, IPagedList 
{ 
    #region IPagedList<T> Members 

    public IEnumerable<T> PageResults { get; set; } 
    public int CurrentPageIndex { get; set; } 
    public int TotalRecordCount { get; set; } 
    public int PageSize { get; set; } 

    #endregion 

    #region IPagedList Members 

    IEnumerable<object> IPagedList.PageResults 
    { 
     get { return PageResults.Cast<object>(); } 
    } 

    #endregion 
} 

現在我可以通過ConcretePagedList<T>到非泛型類/函數

+0

'PagedListPager '類或方法聲明? –

+0

@Gregg抱歉,我會編輯它。 – fearofawhackplanet

+0

我不喜歡在兩個接口中定義屬性,因爲您可以明確地實現它們來執行不同的操作。例如,IPagedList.PageSize {get {return 8;}} IPageList .PageSize {get {return this.PageResults。Count();}}你有第二個接口的唯一原因是提供了強大的輸入,所以Marc的答案似乎消除了該類在屬性上應該有不同結果的能力。 – MPavlak

回答

27

我的方法這裏將使用new來重新聲明PageResults,並且將T作爲Type

public interface IPagedList 
{ 
    int CurrentPageIndex { get; } 
    int TotalRecordCount { get; } 
    int TotalPageCount { get; }   
    int PageSize { get; } 

    Type ElementType { get; } 
    IEnumerable PageResults { get; } 
} 

public interface IPagedList<T> : IPagedList 
{ 
    new IEnumerable<T> PageResults { get; } 
} 

這將,但是,需要「顯式接口實現」,即

class Foo : IPagedList<Bar> 
{ 
    /* skipped : IPagedList<Bar> implementation */ 

    IEnumerable IPagedList.PageResults { 
     get { return this.PageResults; } // re-use generic version 
    } 
    Type IPagedList.ElementType { 
     get { return typeof(Bar); } 
    } 
} 

這種方法使得通過兩個通用和非通用的API完全可用的API。

+0

感謝Marc,我喜歡這個,它與我想出的非常相似,但是有一個更好的實現。 – fearofawhackplanet

+0

優秀 - 簡單,乾淨,易於閱讀。 – Chris

+1

這與「方法」(而不是「屬性」)有何聯繫? – Moop

4

定義兩個接口,第一

public interface IPageSpecification 
    { 
     int CurrentPageIndex { get; } 
     int TotalRecordCount { get; } 
     int TotalPageCount { get; }   
     int PageSize { get; } 
    } 

public interface IPagedList<T> : IPageSpecification 
{ 
    IEnumerable<T> PageResults { get; } 
} 

正如你看到的,IPagedList從IPageSpecification的。在你的方法中,只能使用IPageSpecification作爲參數。在其他情況下,IPagedList - IPagedList的實施者也將從IPageSpecification包含數據

7

一種選擇是創建2個接口這樣的:

public interface IPagedListDetails 
    { 
     int CurrentPageIndex { get; } 
     int TotalRecordCount { get; } 
     int TotalPageCount { get; } 
     int PageSize { get; } 
    } 

    public interface IPagedList<T> : IPagedListDetails 
    { 
     IEnumerable<T> PageResults { get; } 
    } 

然後你的控制:

public class PagedListPager(IPagedListDetails details) 
+0

我曾經考慮過這個問題,但有人認爲接口繼承通常不被認爲是一個好主意? – fearofawhackplanet

+0

接口繼承沒有問題,如果你環顧.NET BCL,你會發現有各種通用接口從非泛型類繼承。 – Ankur

+1

@fearofawhackplanet:恕我直言,接口繼承是未被廣泛使用的。恕我直言,像IList的東西應該來自IReadableByIndex,IMutableByIndex,IAppendable和IRemovableByIndex;數組應該實現了前兩個,但不是最後兩個。 – supercat