Blazor 的依赖注入问题

Posted

技术标签:

【中文标题】Blazor 的依赖注入问题【英文标题】:Dependency Injection issues with Blazor 【发布时间】:2021-09-26 17:55:08 【问题描述】:

我正在使用 .NET 5 和 Blazor,并且我正在使用 DevExpress 创建饼图。

我的问题是,在主页面内部,我有几个 blazor 组件,每个组件都有一个 DevExpress 饼图。

我需要在每个组件内部注入一个类,并且我需要每个组件管理他自己的这个对象的实例,但是看起来我每个 URL 都有一个对象,我该如何解决这个问题?

这是带有一个 DevExpress 圆环图的组件之一的代码:

@using System.Drawing;
@inject IColorPaletteService _colorPaletteService

<hr class="border-gold" />
<h4 class="text-center text-active">Overall</h4>


<DxChart Data="@_genderList" CustomizeSeriesPoint="@PreparePointColor"
         CssClass="w-100">
    <DxChartLegend Visible="false" />

    <DxChartDonutSeries ValueField="@((DashboardValues i) => i.Value)"
                        ArgumentField="@(i => i.Detail)"
                        SummaryMethod="Enumerable.Sum">
    </DxChartDonutSeries>
</DxChart>

<div style="position: relative; top: -26%; left: 90%; transform: translate(-50%, -50%);">
    <h1 class="text-secondary">@Completed%</h1>
</div>


@code 
    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;
    

这是我要注入的对象:

@inject IColorPaletteService _colorPaletteService

这是我要注入的类的代码:

using System.Collections.Generic;
using System.Drawing;

namespace WebClient.Services.Dashboard

    public class ColorPaletteService: IColorPaletteService
    
        private List<Color> ColorList  get; set; 
        private int CurrentColorIndex  get; set; 
        private int ListLenght  get; set; 

        public ColorPaletteService()
        
            CurrentColorIndex = 0;

            ColorList = new List<Color>
            
                ColorTranslator.Fromhtml("#00546C"),
                ColorTranslator.FromHtml("#518197"),
                ColorTranslator.FromHtml("#96898A"),
                ColorTranslator.FromHtml("#C0AFA5"),
                ColorTranslator.FromHtml("#D2C7C3"),
                ColorTranslator.FromHtml("#EDE6E0"),
                ColorTranslator.FromHtml("#BA9764"),
                ColorTranslator.FromHtml("#808080"),
                ColorTranslator.FromHtml("#D0D0D0")
            ;

            ListLenght = ColorList.Count;
        

        public Color GetNextColor
        
            get
            
                if (CurrentColorIndex < ListLenght)
                
                    Color currentColor = ColorList[CurrentColorIndex];

                    // Increase the index for the next iteration
                    CurrentColorIndex += 1;
                    return currentColor;
                

                CurrentColorIndex = 0;
                return ColorList[0];
            
        
    

我遇到的问题是,有范围注入了这个对象,但范围不是每个组件,而是看起来像是一个 URL 对象,这导致类“ColorPaletteService”的函数“GetNextColor”传递了一种随机颜色而不是遵循变量“ColorList”的顺序。

有什么帮助吗?

【问题讨论】:

您遗漏了注册码。我想应该是AddTransient() Inject class by transient not scoped.... Scoped 是每个请求一个... 每次注入类时都会创建一个 .... @MarcosF8 - 旁注,但 Ssystem.Drawing 在 asp.net 中非常可疑。尽量避免Color 【参考方案1】:

您正试图在注入的服务实例中维护特定于组件的状态。相反,您应该维护组件内部的状态。 您的代码可能如下所示:

PieChart.razor

@code

   int currentColorIndex = 0;
   protected void PreparePointColor(ChartSeriesPointCustomizationSettings pointSettings)
    
        currentColorIndex = colorPaletteService.GetNextColor(currentColorIndex, out var color);
        pointSettings.PointAppearance.Color = color;
    

调色板服务为:

public int GetNextColor(int CurrentColorIndex, out Color col)

      col = CurrentColorIndex < ListLenght ? ColorList[CurrentColorIndex] : ColorList[0];
      return CurrentColorIndex >= ListLenght ? 0 : CurrentColorIndex+1;    

并将调色板服务设置为单例。 请注意,blazor 服务器中的瞬态定义不明确。只要会话未断开连接,服务器 WebSocket 就会使会话保持活动状态。所以这里的瞬态行为与传统的 .net 控制器不同。

【讨论】:

“注入服务中的组件特定状态” - 如何避免在 StateService 中出现这种情况? Transient 在任何地方都是一样的:每个请求 1 个实例。 否(即请求什么?这不是 API 请求)。在 Blazor 服务器中,每次创建组件时都会注入瞬态。此外,组件“创建”可能有点棘手。例如,您提出了一个异步请求并决定在等待时显示一个进度条。那样的话,组件可能会被破坏,所以你要重新开始。看一下这个。 docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/… 每个解析请求 1 个。 谁做的?什么时候? 感谢您解决了我的问题,即使 Tansient 运行良好,在这种情况下,拥有一个单例对象似乎可以更好地利用资源。感谢您的帮助!【参考方案2】:

该类应添加为 Transient:

services.AddTansient<IColorPaletteService, ColorPaletteService>();

这将为每个组件提供自己的实例。

【讨论】:

我尝试了 AddTansient,这次运行良好,没有出现错误。谢谢

以上是关于Blazor 的依赖注入问题的主要内容,如果未能解决你的问题,请参考以下文章

Blazor、对象生命周期和依赖注入

Blazor 中的依赖注入与 Razor 组件

Blazor University (44)依赖注入

Blazor University (48)依赖注入 —— Scoped 依赖

Blazor University (46)依赖注入 —— Transient 依赖

Blazor University (49)依赖注入 —— 比较依赖范围