Я создал на контроллере контроллера ContextService, задав в качестве входного параметра HttpContext контроллера.
Передав HttpContext
от контроллера в службу,вы делаете контроллер ответственным за создание этого сервиса.Это тесно связывает контроллер со службой, в то время как целью является слабая связь.
если он использует статическое свойство HttpContext.Current для доступа к сеансу и файлам cookie
как будетэто будет юнит-тест
Не будет.Это важная причина, почему мы создаем абстракции.Некоторые детали в нашей системе не могут подвергаться модульному тестированию, и мы хотим иметь возможность заменить их поддельными реализациями, которые мы используем при тестировании.
Однако хитрость заключается в том, чтобы сделать замененную деталь как можно меньше.и желательно не смешивать его с бизнес-логикой, поскольку замена этого также будет означать, что вы не будете тестировать эту логику.
Вам следует скрыть доступ к HttpContext.Current
за абстракцией.Но когда вы это сделаете, убедитесь, что вы определили абстракцию так, чтобы она лучше всего подходила для вашего приложения.Например, внимательно посмотрите, чего хочет ваш ContextService
.Действительно ли он хочет получить доступ к файлам cookie?Возможно нет.Или он хочет имя или идентификатор текущего вошедшего в систему пользователя?Это более вероятно.Таким образом, вы должны смоделировать свои абстракции вокруг этого.
В качестве примера определите абстракцию, которая позволяет коду приложения получать доступ к информации о зарегистрированном пользователе, используя IUserContext
:
public interface IUserContext
{
string UserName { get; }
}
OneВозможная реализация этой абстракции - та, которая извлекает эту информацию из файла cookie HTTP:
public class CookieUserContext : IUserContext
{
public string UserName => HttpContext.Current.Cookies["name"];
}
Но вы можете легко представить другие реализации, например, когда этот же код приложения должен запускаться вне контекста веб-запроса.например, как часть фоновой операции или изолированного приложения-службы Windows.Это еще одна важная причина для введения абстракций - всякий раз, когда один и тот же код должен работать в разных средах.
Если вам интересно, книга Внедрение зависимостей в .NET Марк Симанн (Mark Seemann) подробно рассказывает об этих видах паттернов и принципах, таких как причины применения DI, предотвращения тесной связи.Второе издание этой книги (выход которого запланирован на осень 2018 г.), которое я и Симанн, даже более подробно рассказываем о вещах, с которыми вы боретесь, таких как предотвращение утечек абстракций, как отделить поведениев классы и проектирование приложений с использованием принципов SOLID.Домашняя страница книги содержит ссылку для загрузки первой главы, которую можно загрузить бесплатно.