Странный дизайн aspnetcore и параметры scope
От: Слава  
Дата: 08.01.22 02:26
Оценка:
Как передать параметры, контекст в scope, созданный стандартным service provider в aspnetcore?

(тут ничего нельзя передать вообще)
using var scope = serviceProvider.CreateScope();


У меня есть тест DI для веб-сервиса aspnetcore. Мне потребовалось имитировать запросы от разных тенантов, чтобы проверить правильность подгрузки всей конфигурации для каждого тенанта.

Сервисы, предоставляющие конфигурацию тенанта, берут данные из сервиса с текущим юзером и тенантом, а этот сервис получает данные из HttpContext, полученный через IHttpContextAccessor (который делается доступным в контейнере DI через startup AddHttpContextAccessor)

Для каждого тенанта нужен отдельный scope, как оно и делается в aspnetcore — на каждый входящий запрос есть отдельный scope.

Только вот когда я создаю этот scope, я не могу в него передать вообще ничего, он просто создаётся — и всё, и внутри него можно запрашивать сервисы у контейнера DI, добавить ничего нельзя.

Мне стало интересно, а как же сам aspnetcore передаёт в очередной scope этот самый HttpContext, ведь если у scope нет никаких параметров, то как это сделать-то?

А вот как, оказывается:
private static AsyncLocal<HttpContextHolder> _httpContextCurrent = new AsyncLocal<HttpContextHolder>();
...
 _httpContextCurrent.Value?.Context;

Впервые слышу про AsyncLocal, иду про него читать: "AsyncLocal<T> represents "ambient" data that is local to a given asynchronous control flow, such as an async method" (исходник https://referencesource.microsoft.com/#mscorlib/system/threading/asynclocal.cs )

Мда. То есть, это как thread local, только в контексте async, потому что в асинхронном окружении в одном потоке исполнения треды могут быть разными в разное время.

Мне одному кажется, что это какой-то несколько странноватый способ передачи контекста, через подобие thread local? А по-другому что, никак?
Re: Странный дизайн aspnetcore и параметры scope
От: Ночной Смотрящий Россия  
Дата: 08.01.22 20:50
Оценка: 5 (1)
Здравствуйте, Слава, Вы писали:

С>Только вот когда я создаю этот scope, я не могу в него передать вообще ничего


У тебя явно какое то странное понимание того что такое scope. Это не какая то загадочная фигня, в которую можно что то там передать, а область жизни инстансов сервисов. Т.е. если сервис объявлен как scoped, то при создании нового scope попытка к нему обратится вызовет запуск фабрики по новой. Ну и время жизни стейта scoped сервиса будет совпадать с временем жизни scope.
При этом сам scope никак не отвечает за то, откуда какой то конкретный инстанс сервиса возьмет свой стейт. Это совершенно отдельная механика, которую ты волен реализовать так как тебе интересно, вне зависимости от того что там в service provider.

С>Мда. То есть, это как thread local, только в контексте async


Ты только что об этом узнал?

С>Мне одному кажется, что это какой-то несколько странноватый способ передачи контекста, через подобие thread local? А по-другому что, никак?


Все зависит от того что ты конкретно хочешь. Можешь, к примеру, просто сделать сервис, реализующий два интерфейса — один публичный, для чтения стейта, второй internal, для его изменения. Публикуешь этот сервис как scoped, в нужный момент инициализируешь из своей инфраструктуры стейт через internal интерфейс, в результате для внешних потребителей получаешь стейт ограниченный скоупом.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[2]: Странный дизайн aspnetcore и параметры scope
От: Слава  
Дата: 09.01.22 02:29
Оценка: +1 -2 :)
Здравствуйте, Ночной Смотрящий, Вы писали:

С>>Только вот когда я создаю этот scope, я не могу в него передать вообще ничего


НС>У тебя явно какое то странное понимание того что такое scope. Это не какая то загадочная фигня, в которую можно что то там передать, а область жизни инстансов сервисов. Т.е. если сервис объявлен как scoped, то при создании нового scope попытка к нему обратится вызовет запуск фабрики по новой. Ну и время жизни стейта scoped сервиса будет совпадать с временем жизни scope.


Ты, НС, как обычно выступаешь в своём репертуаре. Объясняешь очевидные вещи с позиции мудреца, только мудрость та — как у вяленой воблы им. Салтыкова-Щедрина.

НС>При этом сам scope никак не отвечает за то, откуда какой то конкретный инстанс сервиса возьмет свой стейт. Это совершенно отдельная механика, которую ты волен реализовать так как тебе интересно, вне зависимости от того что там в service provider.


Это же очевидно, что scope может иметь некие отличия от родительского контекста. И хорошо бы иметь возможность эти отличия передавать, как это и сделано в Autofac. Конкретный инстанс сервиса обычно берёт свой "стейт" из конструктора, а в конструктор параметры передаются контейнером DI — ну это если нормально делать, чтобы нормально было. А если хочется сложностей — то можно всячески извращаться "у нас тут DI, но мы его использовать не будем".

С>>Мда. То есть, это как thread local, только в контексте async


НС>Ты только что об этом узнал?


Да, я только что об этом узнал. Это изрядно черезжопный способ передачи параметров, вместо явной передачи контекста используется по сути глобальная переменная. Зато с подскоками и плясками вокруг, знанием о которых можно гордиться. Оверинженирингом это называется.
Re[3]: Странный дизайн aspnetcore и параметры scope
От: Ночной Смотрящий Россия  
Дата: 09.01.22 05:33
Оценка: +2
Здравствуйте, Слава, Вы писали:

С>Ты, НС, как обычно выступаешь в своём репертуаре.


К чему этот переход на личности?

НС>>При этом сам scope никак не отвечает за то, откуда какой то конкретный инстанс сервиса возьмет свой стейт. Это совершенно отдельная механика, которую ты волен реализовать так как тебе интересно, вне зависимости от того что там в service provider.

С>Это же очевидно, что scope может иметь некие отличия от родительского контекста.

Опять за рыбу деньги. Scope это не контекст. Если тебе нужен именно контекст — ты должен его сам обеспечить.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.