假设我有以下用于公开分页列表的界面
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 :(得分:29)
我的方法是使用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使API完全可用。
答案 1 :(得分: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)
答案 2 :(得分: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
的数据