Как можем мы сделать зависимость доступной в каждом модуле без включения в каждый API компонента сквозных аспектов приложения?
«Окружающий контекст» доступен любому потребителю через статическое свойство или метод. Потребляющий класс может использовать его следующим образом:
1 2 3 4 | public string GetMessage() { return SomeContext.Current.SomeValue; } |
Чтобы быть полезным в сценариях внедрения зависимостей, контекст сам по себе должен являться абстракцией. При этом должна иметься возможность его модификации извне — это означает, что свойство Current должно разрешать запись значений (быть writable).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public abstract class SomeContext { public static SomeContext Current { get { if (Thread.GetData(Thread.GetNamedDataSlot("SomeContext")) is SomeContext ctx) return ctx; ctx = Default; Thread.SetData(Thread.GetNamedDataSlot("SomeContext"), ctx); return ctx; } set => Thread.SetData(Thread.GetNamedDataSlot("SomeContext"), value); } private static SomeContext Default = new DefaultContext(); public abstract string SomeValue { get; } } |
Окружающкс контекст по структуре похож на антипаттерн «Сервис Локатор». Различие между ними состоит в том, что окружающий контекст предоставляет только экземпляр единственной, сильно типизированной зависимости, тогда как «Сервис Локатор» предоставляет экземпляры для любой запрошенной вами зависимости.
Когда применять окружающий контекст?
- Нужна возможность делать запросы к контексту. Если вам требуется только запрашивать данные (например, о текущем времени)
- Определен подходящее локальное умолчание. Он будет использоваться неявно, поэтому важно, чтобы контекст функционировал корректно.
- Необходима гарантированная доступность. Даже когда определено подходящее локальное умолчание, необходимо обеспечить его защиту от установки в значение null.
Важные характеристики
Не загрязняет API | Неявность |
Всегда доступен | Трудно добиться корректной реализации |
— | Может неправильно работать в некоторых средах исполнения |
Неявность.
При работе с окружающим контекстом вы не сможете, просто взглянув на интерфейс, с уверенностью сказать, используется ли данный контекст конкретным классом.
Сложность реализации
Корректной реализации окружающего контекста может быть достаточно. Как минимум, вы должны гарантировать, что контекст всегда находится в пригодном для использования состоянии — то есть при запросах к нему не должно возникать никаких исключительных ситуаций типа NullReferenceExceptions только из-за того, что одна реализация контекста была удалена без замены ее на другую.
Проблемы с выполнением в ASP.NET
Если окружающий контекст использует TLS, могут возникнуть проблемы при запуске приложения в ASP.NET, поскольку появляется вероятность изменения потоков в определенные моменты жизненного цикла интернет-страниц. При этом не гарантировано, что сохраненные в TLS данные будут скопированы из старого потока в новый. В такой ситуации для хранения специфических данных запроса нужно использовать текущий HttpContext, а не TLS.
Известные способы применения
- Безопасность реализуется через интерфейс System.Security.Principal.IPrincipal, ассоциированный с каждым потоком. Вы можете получить (get) или установить (set) текущего владельца потока, используя методы доступа из Thread.CurrentPrincipal.
- Thread.CurrentCulture и Thread.CurrentUICulture позволяют получить доступ и модифицировать культурный контекст текущей операции. Многие предназначенные для форматирования API, такие как синтаксические анализаторы и конверторы типов, неявно используют текущую культуру, если никакая другая явно не установлена.
- Класс Trace не связан с конкретным потоком, а совместно используется по всему приложению. Задействуя метод Trace.Write, вы можете записать трассировочное сообщение из любого места
Заключение
Если вам нужно запросить зависимость сквозного аспекта на получение ответа, не включенного в оригинальный интерфейс, вы можете применять окружающий контекст, при условии, что для него имеется локальное умолчание. Так вы сможете объединять собственно контекст с поведением, заданным по умолчанию, которое используется всеми клиентами без явного конфигурирования.
Данная статья окончанием паттернов внедрения зависимостей. Мы рассмотрели 4 паттерна внедрения зависимостей, такие как внедрение через конструктор, внедрение через свойство, внедрение через метод и окружающий контекст. Чтобы решить, какой шаблон выбрать для своей конкретной задачи, ниже представлен алгоритм выбора соответствующего паттерна. Пользуйтесь как можно чаще. А если данный алгоритм не поможет, выбирайте внедрение конструктора — вы в этом случае никогда не совершите ужасных ошибок.
farmserher
Farming Simulator – жанр этой игры «симуляторы», которая даст нам побывать на месте фермера, практически как в живую и перенесёт в мир фермерских забот где нужно заботится о животных, полях, машинах. Игра набрала очень много фанатов ещё в ранних версиях, но огромную аудиторию за счёт усовершенствованной графики и физике в игре в этом году в обновлённой версии.
скачать моды для фермер симулятор 2019