Наследование интерфейсов в C # - PullRequest
10 голосов
/ 06 октября 2010

Я пытаюсь преодолеть довольно большую (для меня) проблему, с которой я столкнулся при написании своего приложения.Посмотрите на это, пожалуйста (я постараюсь сократить код для простоты):

У меня есть корневой интерфейс с именем IRepository<T>.Next, IBookRepository : IRepository<Book> Next, конкретный класс, который его реализует: BookRepository : IBookRepository

В классе RepositoryManager, который я объявил private IRepository<IRepoItem> currentRepo;

IRepoItem, это интерфейс, который реализуется классом Book.

Теперь, когда я пытаюсь сделать что-то вроде этого:

currentRepo = new BookRepository();

VisualStudio выдает сообщение об ошибке:

Невозможно неявно преобразовать тип 'BookRepository'в «IRepository».Существует явное преобразование (вам не хватает приведения?)

Я пытался привести в явном виде, но генерируется исключение во время выполнения ...

Я знаю (почти наверняка) что это называется ковариацией и это (вероятно) решено в .Net 4.0.К сожалению, я пишу с использованием фреймворка версии 3.5, и я не могу это изменить.Пожалуйста, дайте мне несколько советов, что делать - как решить эту проблему?Я хотел бы получить currentRepo от RepoFactory, который будет производить несколько видов репозиториев, в зависимости от потребностей пользователя.Я не знаю, разрешены ли здесь ссылки, но я пишу какой-то блог на http://olgatherer.wordpress.com/, где я описываю создание приложений.Мой английский не очень хороший, но я надеюсь, что этого достаточно, чтобы понять меня.Заранее благодарю за ответ.

С уважением, skrzeczowas

Ответы [ 3 ]

4 голосов
/ 06 октября 2010

В .NET 3.5 вы определенно не можете рассматривать IRepository<Book> как IRepository<IRepoItem>.

Нам нужно больше узнать о том, для чего вы используете хранилище в RepositoryManager, чтобы действительно знать, как его решить ... но не могли бы вы создать неуниверсальный интерфейс IRepository, который расширяет IRepository<T> ? Включите в него всех членов, которые не относятся к T. Тогда вы можете объявить currentRepo просто IRepository.

1 голос
/ 06 октября 2010

Попробуйте использовать промежуточный слой (IRep):

    interface IRepository<T>
    {
    }

    interface IRep<T> : IRepository<IRepoItem> where T : IRepoItem
    {
    }

    interface IBookRepository : IRep<Book>
    {
    }

    class BookRepository : IBookRepository
    {
    }

тогда вы можете делать что хотите:

        BookRepository br = new BookRepository();
        IRepository<IRepoItem> currentRepo = br;
0 голосов
/ 06 октября 2010

В .NET 3.5 нет никакой связи между IRepository и IRepository в .NET 4, вы можете достичь чего-то подобного с поддержкой ковариации и контравариантности (но это зависит от объявления интерфейса IRepository)

Aрекомендовал бы использовать не универсальный интерфейс IRepository и выполнить приведение самостоятельно.Я знаю, это не удивительно, но описанная вами функциональность требует поддержки ковариации / контравариантности.

...