问题描述
我查看了如何在 .NET Core 中创建 HttpContext.然后我发现有一个名为 HttpContextFactory
的类,它创建并将 HttpContext
对象分配给 HttpContextAccessor
的 HttpContext
属性班级.为了在我们的代码中使用 HttpContext 对象,我们将 IHttpContextAccessor 注入到需要该对象的类的构造函数中.
I looked at how HttpContext being created in .NET Core. Then I found that there is a class called HttpContextFactory
which create and assign HttpContext
object into a HttpContext
property of HttpContextAccessor
class. And to use HttpContext object in our code, we inject IHttpContextAccessor to the constructor of the class that needs the object.
当我查看 HttpContextAccessor 的实现时,显然它的 HttpContext 属性从私有的 AsyncLocal
变量中获取 HttpContext 对象值,然后在 HttpContextAccessor 上注册为 Singleton.
When I looked at the implementation of HttpContextAccessor, apparently its HttpContext property gets the HttpContext object value from a private AsyncLocal
variable and later on HttpContextAccessor is registered as 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 服务有什么好处?在我看来,两者都会使对象在请求范围内可用.
I'm curious, what is the benefit of doing it this way instead of using a Scope service? It seems to me both would make the object available within a request scope.
如果它是一个范围服务,我认为 HttpContextAccessor 看起来像这样
If it's a scope service, I reckon the HttpContextAccessor will look something like this
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 结合使用.
I would like to know what are the advantages and disadvantages for each approach, so that I'll understand when to use Singleton with AsyncLocal or Scope when creating a library for my project.
推荐答案
只要是单例,解析的 IHttpContextAccessor
实例就可以被单例服务永久持有并正常工作,而它如果单例服务解析范围内的 IHttpContextAccessor
,可能会导致问题.
As long as it is a singleton, the resolved IHttpContextAccessor
instance could be holded permanently by a singleton service and work properly, while it could cause problems if a singleton service resolves a scoped IHttpContextAccessor
.
这篇关于带有 AsyncLocal 与 Scope 服务的单例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!