You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:05:24