Blazor如何为Inject属性传参以预加载指定字典缓存?
实现方案
1. 改造 DictService 增加初始化逻辑
首先需要给服务添加初始化方法,用来接收指定的字典枚举数组,自动检查缓存并按需加载。同时优化并发加载逻辑,避免重复请求:
public enum EnumIntStrDict { Dostawca_Dict = 1, ZazSiecia_Dict = 2, Usluga_podst_Dict = 3, } public class DictService { private readonly ILogger<DictService> _logger; private readonly IHttpService _ihttp; // 全局共享的字典缓存 private static readonly ConcurrentDictionary<EnumIntStrDict, IntStrDict> IntStrDictLocalCache = new(); // 用于控制单个字典的并发加载锁 private readonly ConcurrentDictionary<EnumIntStrDict, SemaphoreSlim> _dictLoadLocks = new(); public DictService(IHttpService ihttp, ILogger<DictService> logger) { _ihttp = ihttp; _logger = logger; } /// <summary> /// 初始化指定字典:检查缓存,未缓存则自动加载 /// </summary> /// <param name="dictNames">需要初始化的字典枚举数组</param> public async Task InitializeAsync(params EnumIntStrDict[] dictNames) { foreach (var dictName in dictNames) { // 获取当前字典的加载锁,避免多线程重复加载 var semaphore = _dictLoadLocks.GetOrAdd(dictName, _ => new SemaphoreSlim(1, 1)); await semaphore.WaitAsync(); try { // 缓存不存在则执行加载 if (!IntStrDictLocalCache.ContainsKey(dictName)) { await FillIntStrDict(dictName); } } finally { semaphore.Release(); } } } private async Task FillIntStrDict(EnumIntStrDict dictName) { // 实现实际的字典加载逻辑(示例) var apiUrl = dictName switch { EnumIntStrDict.Dostawca_Dict => "/api/dicts/dostawca", EnumIntStrDict.ZazSiecia_Dict => "/api/dicts/zazsiecia", EnumIntStrDict.Usluga_podst_Dict => "/api/dicts/uslugapodst", _ => throw new ArgumentOutOfRangeException(nameof(dictName)) }; var dictData = await _ihttp.GetFromJsonAsync<IntStrDict>(apiUrl); if (dictData != null) { IntStrDictLocalCache.TryAdd(dictName, dictData); _logger.LogInformation("字典 {DictName} 已加载并缓存", dictName); } else { _logger.LogWarning("加载字典 {DictName} 失败", dictName); } } /// <summary> /// 对外提供获取缓存字典的方法 /// </summary> public bool TryGetDict(EnumIntStrDict dictName, out IntStrDict dict) { return IntStrDictLocalCache.TryGetValue(dictName, out dict); } }
2. 在Blazor组件中使用
由于@inject本身不支持直接传递参数(DI容器管理的实例为预注册对象),需要在组件的生命周期方法中调用初始化逻辑:
@inject DictService DictService @using YourNamespace; <!-- 替换为EnumIntStrDict所在的命名空间 --> <!-- 组件内容 --> @code { protected override async Task OnInitializedAsync() { // 传入需要预加载的字典枚举 await DictService.InitializeAsync( EnumIntStrDict.Dostawca_Dict, EnumIntStrDict.Usluga_podst_Dict ); await base.OnInitializedAsync(); } }
核心逻辑说明
- 缓存共享:使用
static ConcurrentDictionary保证所有DictService实例共享同一缓存,避免重复加载。 - 并发安全:通过
SemaphoreSlim控制单个字典的加载流程,防止多线程同时触发同一字典的重复请求。 - 按需加载:初始化方法只会加载缓存中不存在的字典,已缓存的直接跳过。
内容的提问来源于stack exchange,提问作者Dorian
相关产品推荐
相关产品推荐

