Заставьте зависимость класса появиться в интерфейсе, не являясь свойством - PullRequest
1 голос
/ 21 февраля 2012

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

У меня есть требование, чтобы класс зависел от ITimer.Создается закрытый член, передается аргумент конструктора, и этому параметру конструктора назначается закрытый член.

Как мне сделать так, чтобы интерфейс как-то объявил этот ITimer, но не как свойство?Не то чтобы я не мог правильно протестировать MyClass, но я думал, что интерфейс должен быть контрактом, которого должен придерживаться класс, поэтому у моего класса есть зависимость, так как мне сделать так, чтобы это появилось в интерфейсе?

public interface IMyInterface
{
  void DoSomething();
}

public class MyClass : IMyInterface
{
  private ITimer MyTimer;

  public MyClass(ITimer timer)
  {
    MyTimer = timer;
  }

  public void DoSomething()
  {

  }
}

Ответы [ 6 ]

3 голосов
/ 21 февраля 2012

Это невозможно сделать с помощью интерфейса в C #.Что вы можете сделать, это унаследовать от экземпляра абстрактного класса интерфейса.

public abstract class AMyClass
{
  protected ITimer MyTimer;

  public AMyClass(ITimer timer)
  {
    MyTimer = timer;
  }

  public abstract void DoSomething();
}

public class MyClass : AMyClass
{
  public override void DoSomething()
  {

  }
}
3 голосов
/ 21 февраля 2012

Это не будет работать, и это хорошо, что это не будет работать:

Ваша зависимость от ITimer не является частью интерфейса , она является частью вашего реализация интерфейса - так что скрывать это от интерфейса - правильная вещь.

Если ВСЕ реализации интерфейса нуждаются в зависимости от ITimerтолько если это так), то для обеспечения этого необходимо добавить объявление интерфейса.

2 голосов
/ 21 февраля 2012

Почему собственность не подходит?Кажется, у вас может быть свойство с частным установщиком, которое делает именно то, что вам нужно.

Другой вариант - это наследовать оба из абстрактного базового класса с защищенным таймером и одновременно реализовывать интерфейс.

Теоретически инъекция зависимостей - это то, что вы ищете.Поэтому, возможно, стоит взглянуть на контейнеры Inversion of Control, возможно, стоит потраченного времени.

2 голосов
/ 21 февраля 2012

Если у вас есть такая зависимость, как ITimer, которую вы явно не хотите видеть в интерфейсе, то это звучит как деталь реализации, поэтому правильно , что она не определена как частьконтракта.Один из подходов - «забыть о ITimer; это может понадобиться только некоторым реализациям, и это касается преобразователя IoC / DI».

Конструкторы, очевидно, не являются частью интерфейса.Единственное, о чем я могу подумать (сохраняя IMyInterface вне API), это иметь интерфейс IMyInterfaceFactory, с методом Create, который принимает ITimer - но это затем вызывает конкретный набор зависимостей, которые могут не отражать фактические реализации.

Если ни один из вышеперечисленных наборов и ITimer не является по существу частью интерфейса, я бы сделал это формально часть интерфейса.

1 голос
/ 21 февраля 2012

Интерфейс - это контракт с возможностью , которую предоставляет класс. Если в интерфейсе нет естественного места для ITimer, то это выглядит как подробность реализации в конкретном классе, который его реализует, и, как таковой, должен оставаться в классе.

0 голосов
/ 21 февраля 2012

Если класс может реализовать ваш интерфейс без использования ITimer, разве он не придерживается интерфейса?Очевидно, что так оно и есть.

Использование ITimer является подробностью реализации, поэтому его не следует представлять в интерфейсе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...