Синглтон с AsyncLocal vs Scope Service - PullRequest
1 голос
/ 26 июня 2019

Я посмотрел, как HttpContext создается в .NET Core. Затем я обнаружил, что существует класс с именем HttpContextFactory, который создает и присваивает объект HttpContext в свойство HttpContext класса HttpContextAccessor. И чтобы использовать объект HttpContext в нашем коде, мы вводим IHttpContextAccessor в конструктор класса, которому нужен объект.

Когда я смотрел на реализацию HttpContextAccessor, очевидно, что его свойство HttpContext получает значение объекта HttpContext из закрытой переменной AsyncLocal, а позже HttpContextAccessor регистрируется как Singleton .

https://github.com/aspnet/AspNetCore/blob/master/src/Http/Http/src/HttpContextAccessor.cs

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Threading;

namespace Microsoft.AspNetCore.Http
{
    public class HttpContextAccessor : IHttpContextAccessor
    {
        private static AsyncLocal<HttpContextHolder> _httpContextCurrent = new AsyncLocal<HttpContextHolder>();

        public HttpContext HttpContext
        {
            get
            {
                return  _httpContextCurrent.Value?.Context;
            }
            set
            {
                var holder = _httpContextCurrent.Value;
                if (holder != null)
                {
                    // Clear current HttpContext trapped in the AsyncLocals, as its done.
                    holder.Context = null;
                }

                if (value != null)
                {
                    // Use an object indirection to hold the HttpContext in the AsyncLocal,
                    // so it can be cleared in all ExecutionContexts when its cleared.
                    _httpContextCurrent.Value = new HttpContextHolder { Context = value };
                }
            }
        }

        private class HttpContextHolder
        {
            public HttpContext Context;
        }
    }
}

Мне любопытно, какая польза от этого, вместо использования Scope ? Мне кажется, что оба сделают объект доступным в пределах области запроса.

Если это сервис области, я считаю, что HttpContextAccessor будет выглядеть примерно так

using System.Threading;

namespace Microsoft.AspNetCore.Http
{
    public class HttpContextAccessor : IHttpContextAccessor
    {
        private HttpContextHolder _httpContextCurrent;

        public HttpContext HttpContext
        {
            get
            {
                return  _httpContextCurrent?.Context;
            }
            set
            {
                if (value != null)
                {
                    _httpContextCurrent = new HttpContextHolder { Context = value };
                }
            }
        }

        private class HttpContextHolder
        {
            public HttpContext Context;
        }
    }
}

Затем используйте его как сервис области

services.TryAddScope<IHttpContextAccessor, HttpContextAccessor>();

Я хотел бы знать, каковы преимущества и недостатки каждого из подходов, чтобы понять, когда использовать Singleton с AsyncLocal или Scope при создании библиотеки для моего проекта.

1 Ответ

1 голос
/ 26 июня 2019

Пока это одноэлементный, разрешенный экземпляр IHttpContextAccessor может постоянно храниться в одноэлементной службе и работать должным образом, хотя это может вызвать проблемы, если одноэлементная служба разрешает область действия IHttpContextAccessor.

...