泛型接口中的索引器

本文关键字:索引 泛型接口 | 更新日期: 2023-09-27 18:27:35

public interface IRepository <T>  where T : EntityBase
{
    T FindBy(object key);
    void Add(T item);
    T this[object key] { get; set; }
    void Remove(T item); 
}

这是一个通用存储库接口的代码示例,该接口由"Domain-Driven-Design .NET C#"一书的作者提供。作者在没有解释的情况下将索引器放在接口T this[object key] { get; set; }其中对象键是对象 ID(就整个系统的标识而言(。作者指出,将索引器放在那里是为了强调存储库应模拟内存中的对象集合。所以我的问题是:将索引器放在接口中有什么好处吗?任何链接,视频,书籍,教程都会对我有很大帮助。谢谢。

泛型接口中的索引器

作者指出,将索引器放在那里是为了强调 存储库应模拟内存中的对象集合。

老实说,我从未听说过这个概念。我在很多项目上看到了存储库模式的实现,我们从未在那里使用索引器。事实上,索引器将用于按 ID 获取项目,这将复制您的T FindBy(object key);

所以,我的总结:在大多数情况下,存储库确实提供了对对象集合的访问,但我看不到向其添加索引器的任何价值。我宁愿专注于您的应用程序所需的事务/查询。


我通常使用BaseRepository : IRepository<T>实现通用IRepository<T>,然后实现特定的存储库UsersRepository : BaseRepository<User>, IUsersRepository IUsersRepository其中接口包含用于用户查询和命令的特定方法。

在这种情况下,索引器用于检索给定对象的键(而不是它在集合中的索引(。在 System.Collections.Generic 中的标准通用接口中,IDictionary<TKey, TValue>是包含该功能的接口。但是,该接口包含更多存储库不会自然公开的功能。

当然,可以实现

这些其他方法,但它们效率不高。提供低效 API 是邀请 API 用户编写低效代码的可靠方法。

作者指出,将索引器放在那里是为了强调存储库应模拟内存中的对象集合。

这听起来像是一个合理的理由。通过"强调"一词,它指向一个重要方面:索引器不一定添加任何功能,它也可以简单地用于提高结果代码的可读性。

假设某个对象具有名为 Resources 的属性,类型为 IRepository<Something> ,如果没有索引器,则只能按如下方式检索特定项:

var theItem = myObject.Resources.FindBy(someKey);

使用索引器,还可以执行以下操作:

var theItem = myObject.Resources[someKey];

在某种程度上,这是个人喜好的问题,但第二个版本可能更直观地识别为仅仅是从列表之类的东西中检索,而不是任意参数化的方法调用。

将索引器放在接口中有什么好处吗?

这是主观的。如果您通过某个找到更有意义的定位对象,为什么不呢?

使用索引器时的主要问题是它们可能会过载。虽然您的接口定义了一个索引器以按 id 获取对象(其中 id object...我会将对象 id 转换为泛型类型...(,按照建议的模式,如果您定义的索引器多于通过标识符检索域对象的索引器,则可能会丢失索引器的含义。

例如:

T this[object key] { get; set; }
T this[T someObject] { get; set; }
T this[int whoKnowsWhatIsIntegerHere] { get; set; }

归根结底,由您来实现索引器,它不会强调或多或少地以正确的方式实现存储库:当存储库在域和数据映射器之间进行调解以将域对象转换为数据时,存储库很好,反之亦然。也就是说,这与什么名称具有方法或它们是否看起来像IList<T>无关......

像收藏一样工作并不意味着看起来像一个收藏......