简体   繁体   English

暴露非泛型版本的泛型接口的模式

[英]Pattern for exposing non-generic version of generic interface

Say I have the following interface for exposing a paged list假设我有以下用于公开分页列表的界面

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

Now I want to create a paging control现在我想创建一个分页控件

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);
    }
}

The paging control has no interest in T (the actual contents of the list).分页控件对T (列表的实际内容)没有兴趣。 It only requires the number of pages, current page etc. So the only reason PagedListPager is generic is so that it will compile with the generic IPagedList<T> paramater.它只需要页数、当前页等。因此PagedListPager是通用的唯一原因是它可以使用通用IPagedList<T>参数进行编译。

Is this a code smell?这是代码味道吗? Should I care that I effectively have a redundant generic?我应该关心我实际上有一个冗余的泛型吗?

Is there a standard pattern in a case like this for exposing an additional non-generic version of the interface, so I can remove the generic type on the pager?在这种情况下是否有标准模式可以公开接口的附加非泛型版本,以便我可以删除寻呼机上的泛型类型?

public class PagedListPager(IPagedList list)

Edit编辑

I thought I'd also add the current way I've solved this problem and invite comments on whether it's a suitable solution:我想我还会添加我解决此问题的当前方式,并邀请评论它是否是一个合适的解决方案:

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
}

Now I can pass ConcretePagedList<T> to non-generic classes/functions现在我可以将ConcretePagedList<T>传递给非泛型类/函数

My approach here would be to use new to re-declare the PageResults , and expose the T as a Type :我的方法是使用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; }
}  

This will, however, require "explicit interface implementation", ie然而,这将需要“显式接口实现”,即

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); }
    }
}

This approach makes the API fully usable via both the generic and non-generic API.这种方法使 API 通过通用和非通用 API 完全可用。

One option is to create 2 interfaces such that:一种选择是创建 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; }
    }

And then your control:然后你的控制:

public class PagedListPager(IPagedListDetails details)

Define two interfaces, first定义两个接口,首先

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

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

As you see, IPagedList is derived from IPageSpecification.如您所见,IPagedList 派生自 IPageSpecification。 In your method, only use IPageSpecification as parameter.在您的方法中,仅使用 IPageSpecification 作为参数。 In other cases, IPagedList - implementers of IPagedList would also contain data from IPageSpecification在其他情况下,IPagedList - IPagedList 的实现者也将包含来自 IPageSpecification 的数据

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM