У меня есть реализация IHostedService
, работающая с использованием .net core 2.2, и я хочу реплицировать IHttpContextAccessor
(но только для использования с областью действия IServiceProvdier, которую я буду называть IRequestServicesAccessor
), и у меня возникают проблемы.
Требования заключаются в том, что IRequestServicesAccessor
должен быть Singleton (например, IHttpContextAccessor
), но при этом иметь доступ к области текущего запроса IServiceProvider
.Это кажется возможным, потому что я пытаюсь просто скопировать IHttpContextAccessor
, но AsyncLocal<>
, кажется, немедленно устанавливает себя в null
после того, как я установил его в значение, поэтому он всегда рассматривается как null
.
Вот копия моей реализации IRequestServicesAccessor
public interface IRequestServicesAccessor
{
IServiceProvider ServiceProvider { get; set; }
}
public class ManualRequestServicesAccessor : IRequestServicesAccessor
{
//This accessor is a tweaked copy of HttpContextAccessor
private static readonly AsyncLocal<ServiceProviderHolder> serviceProviderCurrent = new AsyncLocal<ServiceProviderHolder>();
public IServiceProvider ServiceProvider
{
get
{
return ManualRequestServicesAccessor.serviceProviderCurrent.Value?.ServiceProvider;
}
set
{
ServiceProviderHolder holder = ManualRequestServicesAccessor.serviceProviderCurrent.Value;
if (holder != null)
{
// Clear current ServiceProvider trapped in the AsyncLocals, as its done.
holder.ServiceProvider = null;
}
if (value != null)
{
// Use an object indirection to hold the ServiceProvider in the AsyncLocal,
// so it can be cleared in all ExecutionContexts when its cleared.
ManualRequestServicesAccessor.serviceProviderCurrent.Value = new ServiceProviderHolder { ServiceProvider = value };
}
}
}
private class ServiceProviderHolder
{
public IServiceProvider ServiceProvider;
}
}
Причина, по которой мне это нужно, заключается в том, что я использую Application Insight Azure и, в частности, TelemetryClient
.Из всего, что я прочитал, если вы хотите изменить контекст / свойства TelemetryClient
, чтобы использовать ITelemetryInitializer
и использовать IHttpContextAccessor
, если вам нужна текущая область запроса, потому что ITelemetryInitializer
является одиночным.Но с IHostedService
нет IHttpContextAccessor
.Поэтому мне требуется нечто подобное.В качестве альтернативы мне нужно попробовать другой маршрут без использования ITelemetryInitializer
.
. Вот как работает мой сервис:
- При запуске он устанавливает прослушиватель для сетевых запросов (например, микросервис).связь)
- Получив сообщение, я создаю новую область IServiceProvider, полностью обрабатываю запрос и отправляю ответ (очень похоже на запросы http, но не http)
- Эти сообщения могут занятьдлительное время обработки, и одновременно могут быть сотни.
- Каждый запрос имеет свой контекст, из которого он поступил / для кого он предназначен (мультитенант), и эта информация должна быть помечена в
TelemetryClient
/ ITelemetryInitializer
Любая помощь будет отличной.Спасибо