暴露非泛型接口的非泛型版本的模式
Posted
技术标签:
【中文标题】暴露非泛型接口的非泛型版本的模式【英文标题】:Pattern for exposing non-generic version of generic interface 【发布时间】:2011-10-01 04:17:47 【问题描述】:假设我有以下用于公开分页列表的界面
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)
编辑
我想我也会添加我解决此问题的当前方式,并邀请 cmets 了解它是否是合适的解决方案:
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>
传递给非泛型类/函数
【问题讨论】:
PagedListPager<T>
是类还是方法声明?
@Gregg 抱歉,我会编辑它。
我不喜欢在两个接口中定义属性,因为你可以显式地实现它们来做不同的事情。例如, IPagedList.PageSize getreturn 8; IPageList我在这里的方法是使用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 完全可用。
【讨论】:
谢谢 Marc,我喜欢这个,它与我想出的非常相似,但实现更简洁。 @Moop 取决于签名的变化方式。你有具体的例子吗? @MarcGravell 这样的事情:public interface IBag IFruit GetNextObject(); public interface IBag<T> where T : IFruit new T GetNextObject();
【参考方案2】:
一种选择是创建 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)
【讨论】:
我曾考虑过这一点,但觉得接口继承通常不是一个好主意? 接口继承没有问题,如果你看看.NET BCL你会发现有各种泛型接口继承自非泛型类 @fearofawhackplanet:恕我直言,接口继承未得到充分利用。恕我直言,像 IList 这样的东西应该派生自 IReadableByIndex、IMutableByIndex、IAppendable 和 IRemovableByIndex;数组应该实现了前两个而不是后两个。【参考方案3】:定义两个接口,先
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 的数据
【讨论】:
以上是关于暴露非泛型接口的非泛型版本的模式的主要内容,如果未能解决你的问题,请参考以下文章
ObjectDataSource 未能找到带参数的非泛型方法
ObjectDataSource 'odsX' 找不到没有参数的非泛型方法 'methodX'
返回类型为协议的泛型函数与参数和返回类型为协议的非泛型函数的区别