将 HttpContext 注入 class 并在 .net core 的控制器外部调用 class

Inject the HttpContext into a class and call the class outside the controller in .net core

我需要为每个用户保存一些信息,比如语言和时区,所以我将它们保存在 cookie 中并通过整个网站访问它们。以前更容易访问控制器外部的 httpContext 但在 .Net Core 中,我看到需要使用注入。

看了很多文章,过程是:

  1. 为 class
  2. 创建接口
  3. 创建将访问 HttpContext
  4. 的实际 class
  5. 在Startup.cs处设置注入并注册依赖
  6. 从 Controller 的构造函数中调用 class

在 Microsoft 此处查看详细信息:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-5.0

现在,问题是,这只会将问题向上移动到更高级别,您只能从控制器实例化您的 class,但是如果您需要从另一个地方调用 class ,就像在另一个class中一样,那么你需要像

一样调用构造函数

class同注入:

public class MyClass : IMyClass
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public MyClass(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    ...
}

使用上面注入的新 class:

public class MyClass2
{
   public MyClass2() {
      MyClass myclass = new MyClass(httpContextAccessor)
   }
}

但是此时您还没有 httpContextAccessor 对象,因为它不是从控制器调用的,只是将 httpContextAccessor 传递给这个新的 class。 .. 不可行。

那么,如何正确地做到这一点?如何将 HttpContext 注入 class 以及如何在不依赖控制器的情况下调用 class?

But at this point you don't have the httpContextAccessor

我不太明白这里的意思。 IHttpContextAccessor 被注册为单例服务生命周期,这意味着我们可以从应用程序的任何地方获取它。

比方说这种情况,MyClass2需要一个MyClass的对象,所以,哪里可以做到像

public class MyClass2
{
   public MyClass2(IHttpContextAccessor httpContextAccessor) 
   {
      MyClass myclass = new MyClass(httpContextAccessor)
   }
}

// Some service make use of MyClass2, MyClass2 not register on DI
public class DemonstrateService
{
   private readonly MyClass2 myClass2;

   public DemonstrateService(IHttpContextAccessor httpContextAccessor)
   {
      myClass2 = new MyClass2(httpContextAccessor);
   }
}

// Some service make use of MyClass2, MyClass2 got registered on DI
public class DemonstrateService
{
   private readonly MyClass2 _myClass2;

   public DemonstrateService(MyClass2 myClass2)
   {
      _myClass2 = myClass2;
   }
}

// Register in DI
services.AddScoped<DemonstrateService>();
services.AddScoped<MyClass2>();
...

// Using it anywhere, it's not restricted to Controller

作为旁注,我们可以很容易地看到这种嵌套依赖关系组织得不太好。但是我们以自己的方式实现代码。 github 上有很多干净的代码 .Net 核心存储库,我们可以从中获取一些基础知识。

似乎通过在模型中添加构造函数 class 来注入 HttpContext 是不可能的,因为 LINQ 在执行查询时也会调用构造函数。我发现我可以在模型外部使用 STATIC class 来保留我需要的所有设置,比如“UserTimezone”。因此,我没有尝试从静态 class 中读取 Cookie,而是在保存值的位置设置了一个静态字符串 属性,并且该值似乎在整个网页请求周期中都保持不变。

基本上,我这样做了,并且对我有用:

  1. 创建一个 ActionFilter 并在每个控制器上调用它
  2. 在 Startup.cs
  3. 中设置此过滤器的注入
  4. 然后将 HttpContext 从 Controller 注入到 Filter
  5. 在过滤器中,我添加了一个函数来读取 Cookie 中的值并将它们保存到静态 class(即 MyGlobalStatic.UserTimezone)
  6. 然后我在所有需要这些值的模型中使用静态 class(即我需要 UserTimeZone 将 DateTime 字段从数据库通用时间转换为用户本地时间)。