我研究了如何在.NET Core中创建HttpContext。然后,我发现有一个名为HttpContextFactory
的类,它创建HttpContext
对象并将其分配到HttpContext
类的HttpContextAccessor
属性中。为了在代码中使用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与AsyncLocal或Scope一起使用。
答案 0 :(得分:1)
只要是单例,已解析的IHttpContextAccessor
实例可以由单例服务永久保存并正常工作,而如果单例服务解析范围为IHttpContextAccessor
的实例可能会引起问题。 / p>
答案 1 :(得分:0)
我猜想原因之一可能是Asp.Net Core IServiceProvider不允许将作用域依赖项注入到Singleton类中。那可能是背后的重大决定。如果事情已经按照您的建议进行了范围划分,那么使用它的所有类都必须进行范围划分。但是有趣的是,一旦请求得到处理,HTTPContext就会为空。