Как добавить логирование в статический класс, не теряя возможности модульного тестирования? - PullRequest
0 голосов
/ 25 июня 2018

ПРИМЕЧАНИЕ: Я понимаю, что этот вопрос похож на эту SO-тему , но я спрашиваю о конкретном случае здесь, поэтому, пожалуйста, не закрывайте этот вопрос как дубликатиз этого.

Я пытаюсь сделать мой C # более функциональным, и читал «Функциональное программирование в C #» Энрико Буонанно.Один из методов, которые он показывает, - это класс Try, который позволяет изящно обрабатывать исключения.Вы можете увидеть код для Try класса здесь .

Это все очень аккуратно, но в реальном приложении я бы хотел регистрировать исключения.Поскольку его класс статичен, я не вижу способа сделать это.Как объяснено в связанном вопросе SO выше (среди прочего), внедрение в статический класс либо невозможно, либо не является хорошей идеей.

Единственные варианты, которые я вижу, это:

  1. Требование к потребляющему коду для создания экземпляра класса Try (в настоящее время это невозможно с его кодом), в отличие от вызова статического метода.Это делает код намного менее чистым

  2. Добавление статического свойства ILogger в класс Try и установка его перед использованием класса.Я не хочу этого делать, поскольку класс Try будет использоваться как на клиенте, так и на сервере в моем приложении, и регистратор будет отличаться в двух случаях

  3. Добавление параметра ILogger в методы класса.Мне не нравится это по тем же причинам, что и в 1.

  4. Доступ к средству разрешения зависимостей внутри класса try и получение экземпляра регистратора.Это будет означать, что код, использующий Try, также в конечном итоге будет регистрироваться в файле, что не является хорошей идеей.Подход кажется таким чистым и аккуратным, но в нем также отсутствует очевидная базовая функция.

1 Ответ

0 голосов
/ 25 июня 2018

Почему бы статическому методу не создать экземпляр класса, как тогда вызвать частный метод экземпляра, который выполняет работу?Я не знаком с Try, но вы могли бы сделать что-то вроде этого (предупреждение - воздушный код!) ...

public class Try<T> {
  // Assuming NInject, but same applies to any other container
  [Inject]
  ILogger Logger { get; set; }

  private Try() {
    // stops anyone from outside this project from creating an instance of Try
  }

  public static Exceptional<T> Do(Action f) {
    Try<T> t = new Try<T>();
    return t.DoPrivate<T>(f);
  }

  private Exceptional<T> DoPrivate<T>(Action f) {
    // This is an instance method, so has access to the injected logger
    try {
      return f();
    } catch (Exception ex) {
      Logger.Log(ex.Message);
      return ex;
    }
  }
}

Это помогает?Как я уже сказал, я не знаком с его кодом, поэтому вам, возможно, придется немного его настроить, но я думаю, что это даст вам то, что вы хотите.

...