我研究了一下在.NET Core中如何创建HttpContext。然后我发现有一个叫做HttpContextFactory
的类,它创建并将HttpContext
对象分配给HttpContextAccessor
类的HttpContext
属性。为了在我们的代码中使用HttpContext对象,我们需要将IHttpContextAccessor注入到需要该对象的类的构造函数中。
当我查看HttpContextAccessor的实现时,显然它的HttpContext属性从一个私有的AsyncLocal
变量获取HttpContext对象的值,然后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 with AsyncLocal或Scope。
DefaultHttpContextFactory
本身并没有注册为Singleton
,而是以Transient
的方式注册。您可以在此文件中查看:https://github.com/aspnet/AspNetCore/blob/f3f9a1cdbcd06b298035b523732b9f45b1408461/src/Hosting/Hosting/src/WebHostBuilder.cs#L284。该类负责设置 HttpContext 的值。 - muhihsanIHttpContextAccessor
。这有点说得通 :) 但我能问一下,在我们的 Web 项目中何时需要从单例类访问IHttpContextAccessor
的场景吗? - muhihsan