【问题标题】:"Rename" inherited methods in interface in C#C# 接口中的“重命名”继承方法
【发布时间】:2010-11-09 20:34:23
【问题描述】:

在开发 ASP.NET MVC 应用程序(使用 .NET 3.5、ASP.NET MVC 1.0 和实体框架)时,我正在尝试理解 Repository Pattern。我已经获得了足够的依赖注入,并且都可以使用一种控制器和一种实体类型,但现在我已经实现了对不同类型之间关系的支持,但我被卡住了。

在我见过的所有示例中,存储库接口都称为IContactsRepository,并且包含仅与Contact 项目相关的(CRUD)方法。我想实现Contacts 的分组,所以我有一个名为Group 的实体类型和一个IGroupRepository 接口,用于处理组上的(CRUD)操作。

  • 与多个实体类型相关的方法属于哪里(在这种情况下,例如方法 AddToGroup,它将 Contact 添加到 Group)?

我尝试为存储库创建更大的继承结构,并在其中创建了以下接口:

ITypedRepository<T>
{
    IEnumerable<T> GetAll();
    T Get(int id);
    bool Add(T newObj);
    bool Edit(T editedObj);
    bool Delete(int id);
}

IContactsRepository : ITypedRepository<Contact> { }

IGroupsRepository : ITypedRepository<Group> {
    bool AddToGroup(int contactId, int groupId);
}

IRepository : IContactsRepository, IGroupsRepository

然后我尝试创建一个继承IRepository的主仓库,如下:

public class EntitiesRepository : IRepository
{
    IEnumerable<Contact> IRepository<Contact>.Get()
    {
        throw new NotImplementedException();
    }
    IEnumerable<Group> IRepository<Group>.Get()
    {
        throw new NotImplementedException();
    }
    // Etc. All methods were generated by hitting [Ctrl]+[.] with the cursor on
    // the interface inheritance reference to IRepository and selecting
    // "Explicitly implement IRepository"
}

一旦我尝试使用此代码从我的控制器调用存储库中的方法之一

var contacts = _repository.Get();

我收到一条构建错误消息,说明 Get&lt;Contact&gt;()Get&lt;Group&gt;() 之间的歧义是通过 IContactsRepository 继承的,而 Get&lt;Group&gt;() 是通过 IGroupsRepository 传来的。我知道这是不允许的,因为IRepository inherits the same generic interface with different types (请参阅链接文章中的示例5)。

  • 现在,由于我是通过其他接口继承的,是否有机会“覆盖”这些方法的名称,例如如下所示?

    IContactsRepository : ITypedRepository<Contact>
    {
        IEnumerable<Contact> GetContacts = ITypedRepository<Contact>.Get();
        ...
    }
    

这样,我可以从IRepository.Getcontacts 毫无歧义地访问它。是否有可能,或者是否有任何解决此问题的方法?

还有一个新问题,需要澄清一下:

  • 无论如何在控制器的调用中指定我想要哪个Get() 方法?

  • 解决我最初的问题的最佳方法是什么 - 需要一个可以处理很多事情的存储库,而不仅仅是一种实体类型?

编辑:添加了Repository类的代码示例并从Controller调用。

【问题讨论】:

  • 考虑显式接口实现。有关详细信息,请参阅stackoverflow.com/questions/1077816/…
  • 感谢您的回复 - 我已经尝试过了,并更新了更多代码以进行澄清。
  • 每看不懂这个问题就给这个问题加一分
  • 甜甜的酒精,让我从这个问题中解脱出来。
  • zvolkov 和 Chris:很抱歉这么长的文字。我对此理解不够好,无法将其缩短。总之,我想问的是a)如何为多种类型的实体设置存储库以及b)如何解决在使用不同类型多次继承相同的通用接口时出现的问题。

标签: c# design-patterns interface repository-pattern multiple-inheritance


【解决方案1】:

我认为您不需要所有这些复杂性。将联系人添加到组时,您正在更改组。我假设您在 Group 类上有一组联系人。将联系人添加到群组后,您只需保存群组即可。那么你真的需要一个 AddContactToGroup 方法吗,只需要 Group 存储库接口上的 Save 方法就可以完成同样的工作。此外,您不需要为 Group 上的每个新关系属性使用新方法。

对于Save方法本身的实现,如果使用NHibernate,只需调用相关方法即可。

【讨论】:

    【解决方案2】:

    除了 CRUD 方法之外,您的 IGroupRepository 上可能还有专门的方法:

    IGroupRepository : ITypedRepository<Group>
    {
        bool AddContactToGroup(Group g, Contact C);
    }
    

    【讨论】:

    • 谢谢!我已经有了,但是当我尝试这个时,继承链对我不起作用。
    【解决方案3】:

    添加调用显式实现的具有明确名称的方法:

    public class EntitiesRepository : IRepository
    {
        IEnumerable<Contact> IRepository<Contact>.Get()
        {
            // Return something
        }
        IEnumerable<Group> IRepository<Group>.Get()
        {
            // Return something
        }
    
        public IEnumerable<Contact> GetContacts()
        {
            return (this as IRepository<Contact>).Get();
        }
    
        public IEnumerable<Group> GetGroups()
        {
            return (this as IRepository<Group>).Get();
        }
    }
    

    【讨论】:

    • 确实很好!但它并没有真正解决我的问题:如果我这样做,接口 IRepository 中没有任何东西可以确保这个方法存在(除非我定义了每个命名的方法,但这就是我想要避免的第一名...)。这意味着我无法通过接口将控制器与存储库分离,因此我将无法以任何简单的方式对其进行测试...
    • 为什么需要确保它存在?仅当您要显式调用它时,它才需要存在。无论如何,Get 方法始终作为 IRepository 的显式实现存在。在控制器中,您将存储库声明为 IContactsRepository 或 IGroupRepository,而不是 IRepository,因此不会有歧义。
    猜你喜欢
    • 2011-08-13
    • 2011-01-01
    • 2013-02-07
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 2011-09-05
    • 2022-08-12
    • 1970-01-01
    相关资源
    最近更新 更多