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>これで、非ジェネリック クラス/関数に渡すことができます

4

3 に答える 3

31

ここでの私のアプローチは、newを再宣言し、を:としてPageResults公開するために使用することです。TType

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の両方を介してAPIを完全に使用できるようになります。

于 2011-07-08T10:40:30.770 に答える
7

1 つのオプションは、次のような 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)
于 2011-07-08T10:32:51.937 に答える
5

最初に 2 つのインターフェースを定義します。

    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 からのデータも含まれます。

于 2011-07-08T10:32:19.370 に答える