IHttpContextAccessor альтернатива для доступа к области IServiceProvider для IHostedService - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть реализация 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

Любая помощь будет отличной.Спасибо

...