Asp.net core依赖注入服务生存期踩坑记录
写在开头
今天我本想实现组件全局共享数据(状态管理),保存工厂名,用户登录id,设备编码等字段,以便全局共享。
但我在a组件设置的值到了b组件就不见了。
遇到的问题,与依赖注入服务生存期有关,我们知道依赖注入服务一共有三种:
AddScoped
:作用域
AddTransient
:瞬时
AddSingleton
:单例
内容
set state,在另一个组件中点击事件打印state
public record AppState
{
public string Factory { get; private set; }
public string UserId { get; private set; }
public string EquipId { get; private set; }
public void SetFactory(string factory)
{
if (string.IsNullOrWhiteSpace(factory))
return;
Factory = factory;
}
public void SetUserId(string userId)
{
if (string.IsNullOrWhiteSpace(userId))
return;
UserId = userId;
}
public void SetEquipId(string equipId)
{
if (string.IsNullOrWhiteSpace(equipId))
return;
EquipId = equipId;
}
}
//program.cs
builder.Services.AddScoped<AppState>();
//Home.razor
@inject AppState appState
appState.SetEquipId(Id);
appState.SetFactory(Factory);
Console.WriteLine("这里是home:{0}",appState);
//login.razor
@inject AppState appState
@inject UserAuthenticationStateProvider UserAuthenticationStateProvider
var a = await UserAuthenticationStateProvider.GetAuthenticationStateAsync();
appState.SetUserId(a.User.FindFirst("EmployeeNo").Value);
Console.WriteLine("这里是login:{0}",appState);
navMan.NavigateTo($"/{appState.Factory}/{appState.EquipId}",true);//跳转回home
可以看到,数据不见了
罪魁祸首则是NavigateTo
方法的true
参数
翻阅微软文档,以下解释:
如果为 true,则绕过客户端路由并强制浏览器从服务器加载新页面,无论 URI 是否通常由客户端路由器处理。
强制加载页面,那么也就是在这里点击了刷新或者直接修改路由进行导航,它的scoped
就改变了
那么去掉true,让路由帮我们完成:
发现状态获取成功
此时新开一个标签页:http://localhost:5000/DP10/888
打印出的结果与之前不同了,可我们在原先第一个标签页,也就是http://localhost:5000/DP02/123
,打印出的结果仍是DP02
,由此可知,作用域仅限于当前标签页
"对于 Web 应用,指定了作用域的生存期指明了每个客户端请求(连接)创建一次服务。"
接下来我们测试singleton
发现不管在哪里设置,在哪里获取,都是同步的,举个例子:
a用户登录系统,设置
userid
为a,b用户登录系统,设置userid
为b,此时,a用户的userid
也变成了b"来自依赖关系注入容器的服务实现的每一个后续请求都使用同一个实例。"
最后,是transient:
state 即用即弃,也会造成a页面赋了值,b页面拿不到的情况
"在处理请求的应用中,在请求结束时会释放暂时服务。 此生存期会产生每个请求的分配,因为每次都会解析和构建服务。"
写在最后
不同的服务适用于不同的业务:
如果我是保存用户数据,显然是scoped