将 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 中,我看到需要使用注入。
看了很多文章,过程是:
- 为 class
创建接口
- 创建将访问 HttpContext
的实际 class
- 在Startup.cs处设置注入并注册依赖
- 从 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,而是在保存值的位置设置了一个静态字符串 属性,并且该值似乎在整个网页请求周期中都保持不变。
基本上,我这样做了,并且对我有用:
- 创建一个 ActionFilter 并在每个控制器上调用它
- 在 Startup.cs
中设置此过滤器的注入
- 然后将 HttpContext 从 Controller 注入到 Filter
- 在过滤器中,我添加了一个函数来读取 Cookie 中的值并将它们保存到静态 class(即 MyGlobalStatic.UserTimezone)
- 然后我在所有需要这些值的模型中使用静态 class(即我需要 UserTimeZone 将 DateTime 字段从数据库通用时间转换为用户本地时间)。
我需要为每个用户保存一些信息,比如语言和时区,所以我将它们保存在 cookie 中并通过整个网站访问它们。以前更容易访问控制器外部的 httpContext 但在 .Net Core 中,我看到需要使用注入。
看了很多文章,过程是:
- 为 class 创建接口
- 创建将访问 HttpContext 的实际 class
- 在Startup.cs处设置注入并注册依赖
- 从 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,而是在保存值的位置设置了一个静态字符串 属性,并且该值似乎在整个网页请求周期中都保持不变。
基本上,我这样做了,并且对我有用:
- 创建一个 ActionFilter 并在每个控制器上调用它
- 在 Startup.cs 中设置此过滤器的注入
- 然后将 HttpContext 从 Controller 注入到 Filter
- 在过滤器中,我添加了一个函数来读取 Cookie 中的值并将它们保存到静态 class(即 MyGlobalStatic.UserTimezone)
- 然后我在所有需要这些值的模型中使用静态 class(即我需要 UserTimeZone 将 DateTime 字段从数据库通用时间转换为用户本地时间)。