Переименовать унаследованные методы в интерфейсе в C #

Я пытаюсь понять Repository Pattern при разработке приложения ASP.NET MVC (с использованием .NET 3.5, ASP.NET MVC 1.0 и Entity Framework). Я зашел достаточно далеко, чтобы внедрить зависимость и все работало с одним контроллером и одним типом сущности, но теперь я дошел до реализации поддержки связи между разными типами, и я застрял.

Во всех примерах, которые я видел, интерфейс репозитория называется что-то вроде IContactsRepository и содержит (CRUD) методы, которые относятся только к Contact элементам. Я хочу реализовать группировку 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<Contact>(), унаследованным через IContactsRepository, и Get<Group>(), пришедшим через IGroupsRepository. Я понял, что это запрещено, потому что IRepository наследует тот же общий интерфейс с разные типы (см. пример 5 в связанной статье).

  • Теперь, поскольку я наследую через другие интерфейсы, есть ли шанс, что я могу «переопределить имена» этих методов, например, как показано ниже?

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

Таким образом, я могу получить к нему доступ из IRepository.Getcontacts без какой-либо двусмысленности. Возможно ли это или есть ли способ решения этой проблемы?

И новый вопрос для уточнения:

  • Есть ли способ указать в вызове контроллера, какой из Get() методов мне нужен?

  • Как лучше всего решить мою первоначальную проблему - потребность в репозитории, который обрабатывает множество вещей, а не только один тип сущности?

РЕДАКТИРОВАТЬ: Добавлен пример кода класса Repository и вызова из Controller.


person Tomas Aschan    schedule 10.07.2009    source источник
comment
Рассмотрим явную реализацию интерфейса. Для получения дополнительной информации см. stackoverflow.com/questions / 1077816 /   -  person mmx    schedule 11.07.2009
comment
Спасибо за ответ - я пробовал это и обновил еще немного кода для пояснения.   -  person Tomas Aschan    schedule 11.07.2009
comment
Голосование по этому вопросу по одному баллу каждый раз, когда я не понимаю его   -  person Chris McCall    schedule 11.07.2009
comment
Сладкий, сладкий алкоголь, избавь меня от этого вопроса.   -  person quillbreaker    schedule 11.07.2009
comment
Зволков и Крис: Прошу прощения за длинный текст. Я недостаточно хорошо понимаю это, чтобы сформулировать это короче. Таким образом, я пытаюсь спросить: а) как настроить репозиторий для нескольких типов сущностей и б) как обойти проблемы, возникающие при наследовании одного и того же универсального интерфейса несколько раз с разными типами.   -  person Tomas Aschan    schedule 11.07.2009


Ответы (3)


Думаю, вам не нужна вся эта сложность. Когда вы добавляете контакт в группу, вы меняете группу. Я предполагаю, что у вас есть набор контактов в групповом классе. После добавления контакта в группу просто нужно сохранить группу. Так что вам действительно нужен метод AddContactToGroup, просто метод Save в интерфейсе репозитория группы будет выполнять ту же работу. Также вам не нужен новый метод для каждого нового реляционного свойства в Group.

Для реализации самого метода Save, если вы используете NHibernate, вам нужно только вызвать соответствующий метод.

person Serkan    schedule 01.01.2010

У вас, вероятно, будут специализированные методы в вашем IGroupRepository в дополнение к методам CRUD:

IGroupRepository : ITypedRepository<Group>
{
    bool AddContactToGroup(Group g, Contact C);
}
person n8wrl    schedule 10.07.2009
comment
Спасибо! Это у меня уже есть, но это цепочка наследования, которая у меня не работает, когда я пытаюсь это сделать. - person Tomas Aschan; 11.07.2009

Добавьте методы с однозначными именами, которые вызывают явные реализации:

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();
    }
}
person Thomas Levesque    schedule 10.07.2009
comment
Это действительно очень хорошо! Но на самом деле это не решает мою проблему: если я сделаю это таким образом, в интерфейсе IRepository не будет ничего, что гарантирует, что этот метод существует (если я не определю каждый именованный метод, но этого я хотел избежать в первое место...). Это означает, что я не могу отделить Контроллер от Репозитория через интерфейс, и поэтому я не смогу протестировать его каким-либо простым способом ... - person Tomas Aschan; 11.07.2009
comment
Зачем нужно убедиться, что он существует? Он должен существовать только в том случае, если вы собираетесь называть его явно. В любом случае метод Get всегда существует как явная реализация IRepository ‹T›. В контроллере вы объявите репозиторий как IContactsRepository или IGroupRepository, а не как IRepository, чтобы не было двусмысленности. - person Thomas Levesque; 11.07.2009