Если я правильно понимаю ваш вопрос, ваш вопрос касается доступа к сервисам с заданной областью из контекста одноэлементного сервиса?
Предполагается, что ваше приложение ASP. Net WebAPI (не Core), вам нужно перехватить HttpRequestMessage
для того, чтобы иметь доступ к области запроса.
Во-первых, вам нужно где-то хранить сообщение запроса, и, поскольку вы хотите получить доступ к сообщению запроса из службы singleton, новая служба также должна быть singleton сервисом:
interface IHttpRequestAccessor
{
HttpRequestMessage Request { get; set; }
}
class HttpRequestAccessor : IHttpRequestAccessor
{
private readonly AsyncLocal<HttpRequestMessageHolder> _currentRequest =
new AsyncLocal<HttpRequestMessageHolder>();
public HttpRequestMessage Request
{
get => _currentRequest.Value?.Value;
set
{
HttpRequestMessageHolder holder = _currentRequest.Value;
if (holder != null)
{
holder.Value = null;
}
if (value != null)
{
_currentRequest.Value = new HttpRequestMessageHolder { Value = value };
}
}
}
private class HttpRequestMessageHolder
{
public HttpRequestMessage Value { get; set; }
}
}
builder.RegisterType<HttpRequestAccessor>()
.As<IHttpRequestAccessor>()
.SingleInstance();
Как это работает?
Этот класс предоставляет свойство для получения и установки HttpRequestMessage
для текущий асин c контекст выполнения. Поскольку контекст данных различен для каждого запроса и наследуется на всех этапах конвейера запросов WebAPI, мы могли бы установить его в одном месте, а затем использовать в другом месте для того же HTTP-запроса. Это та же концепция, что и IHttpContextAccessor
в ASP. Net Базовых приложениях.
Теперь нам нужно где-то захватить и установить IHttpRequestAccessor.Request
. делегирующий обработчик является хорошим вариантом:
class CaptureHttpRequestMessageHandler : DelegatingHandler
{
private readonly IHttpRequestAccessor _requestMessageAccessor;
public CaptureHttpRequestMessageHandler(IHttpRequestAccessor requestMessageAccessor)
{
_requestMessageAccessor = requestMessageAccessor;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
if (_requestMessageAccessor != null)
{
_requestMessageAccessor.Request = request;
}
return base.SendAsync(request, cancellationToken);
}
}
И добавьте его в конфигурацию:
GlobalConfiguration.Configuration.MessageHandlers.Add(
new CaptureHttpRequestMessageHandler(/* resolve services here */));
В конце концов, введите IHttpRequestAccessor
в AuthRefreshTokenProvider
и удалите Logic
.
Когда потребуется Logic
, разрешите его на лету, используя:
_httpRequestAccessor.Request.GetDependencyScope().GetService(typeof(Logic));
Пока вызывается AuthRefreshTokenProvider
, когда существует HTTP-запрос, это должно работать.