Blazor依赖注入问题:如何实现每个组件独享IColorPaletteService实例
解决方案
你的问题根源是Blazor中Scoped生命周期的服务特性:Scoped服务在同一用户页面会话(Blazor Server为SignalR连接生命周期,Blazor WASM为整个单页应用生命周期)内共享,所以同一页面下的多个组件会拿到同一个IColorPaletteService实例,多个组件同时调用GetNextColor时会互相干扰索引计数,导致颜色顺序混乱。
你可以选择以下任意一种方案实现每个组件独享服务实例:
方案1:修改服务注册为瞬时(Transient)生命周期
瞬时生命周期的服务每次被注入时都会创建全新实例,刚好满足每个组件独享实例的需求。
- 找到你的服务注册代码位置:
- Blazor Server .NET 5:
Startup.cs文件的ConfigureServices方法 - Blazor WASM .NET 5:
Program.cs文件的服务配置段
- Blazor Server .NET 5:
- 将原有的Scoped注册替换为Transient注册:
// 注释/删除原来的Scoped注册 // services.AddScoped<IColorPaletteService, ColorPaletteService>(); // 改为Transient注册 services.AddTransient<IColorPaletteService, ColorPaletteService>();
此方案无需修改任何组件代码,修改注册后每个组件注入时都会拿到独立的服务实例,各自的颜色索引从0开始计数,完全互不干扰。
方案2:组件内部直接实例化服务(无需修改服务注册)
因为你的ColorPaletteService是无参构造函数,没有其他依赖的注入服务,你可以直接在组件内部创建实例,完全绕开DI容器的生命周期限制:
- 删除组件顶部的注入语句:
@inject IColorPaletteService _colorPaletteService - 在组件的
@code块中手动初始化服务实例:
@code { // 每个组件自己创建专属的服务实例 private readonly IColorPaletteService _colorPaletteService = new ColorPaletteService(); // 以下原有代码保持不变 private IEnumerable<DashboardValues> _genderList; private int Completed { get; set; } protected override void OnInitialized() { // 原有逻辑不变 base.OnInitialized(); _genderList = new List<DashboardValues> { new DashboardValues {Id = 1, Detail = "Completed", Value = 90}, new DashboardValues {Id = 1, Detail = "Remaining", Value = 10}, }; Completed = _genderList.First(x => x.Detail == "Completed").Value; } protected void PreparePointColor(ChartSeriesPointCustomizationSettings pointSettings) { pointSettings.PointAppearance.Color = _colorPaletteService.GetNextColor; } }
此方案无需修改全局服务配置,灵活性更高。
两种方案都可以保证每个饼图组件的取色顺序严格按照你预设的ColorList顺序输出,不会出现颜色混乱的问题。
内容的提问来源于stack exchange,提问作者MarcosF8
相关产品推荐
相关产品推荐

