Blazor:如何使用来自具有 2 个不同状态的 2 个不同页面的组件

     2023-03-27     243

关键词:

【中文标题】Blazor:如何使用来自具有 2 个不同状态的 2 个不同页面的组件【英文标题】:Blazor: How to use a component from 2 different pages with 2 different states 【发布时间】:2021-12-20 21:40:45 【问题描述】:

在 Blazor 应用程序中,我想使用来自两个不同页面的组件。组件使用服务来维护其状态。但是每个页面都需要让组件使用不同的状态。以下是我的想法(使用默认的 Counter 组件进行演示)。

CounterService.cs

namespace TestTwoInterfaceToOneService.Shared

    public interface ICounterServiceA
    
        int CurrentCount  get; set; 
        void IncrementCount();
    

    public interface ICounterServiceB
    
        int CurrentCount  get; set; 
        void IncrementCount();
    

    public class CounterService : ICounterServiceA, ICounterServiceB
    
        public int CurrentCount  get; set; 
        public void IncrementCount()
        
            CurrentCount++;
        
    

在 Program.cs 添加:

builder.Services.AddScoped<ICounterServiceA, CounterService>();
builder.Services.AddScoped<ICounterServiceB, CounterService>();

Counter.razor

<h1>Counter</h1>
<p>Current count: @CounterService.CurrentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code 
    [Parameter]
    public CounterService CounterService  get; set; 

    private void IncrementCount()
    
        CounterService.CurrentCount++;
    

PageA.razor

@page "/pagea"
@inject ICounterServiceA CounterServiceA

<h3>Page A</h3>
<Counter CounterService="CounterServiceA" /> @*<-- Error: Cannot convert from ICounterServiceB to CounterService*@

PageB.razor

@page "/pageb"
@inject ICounterServiceB CounterServiceB

<h3>Page B</h3>
<Counter CounterService="CounterServiceB" /> @*<-- Error: Cannot convert from ICounterServiceB to CounterService*@

当我尝试将服务传递给组件时,我收到错误“无法从 ICounterServiceB 转换为 CounterService”。我发现使用 2 个指向相同具体实现的相同接口确实给了我 2 个作用域实例。但是,我不知道如何将这些实例传递给组件。

有没有我遗漏的部分?或者,这应该以其他方式完成吗?

解决方案

结合 Henk 的答案和 Brian 的 cmets,我想出的解决方案是:

CounterService.cs

namespace TestTwoInterfaceToOneService.Shared

    public class CounterService
    
        public int CurrentCount  get; set; 
        public void IncrementCount()
        
            CurrentCount++;
        
        public void ResetCount()
        
            CurrentCount = 0;
        
    

CounterStateService.cs

using System.Collections.Generic;
namespace TestTwoInterfaceToOneService.Shared

    public interface ICounterStateService
    
        CounterService this[string key]  get; 
    

    public class CounterStateService : ICounterStateService
    
        private Dictionary<string, CounterService> counterServices = new();
        public CounterService this[string key]
        
            get
            
                if (!counterServices.ContainsKey(key))
                
                    counterServices.Add(key, new CounterService());
                
                return counterServices[key];
            
        
    

在 Program.cs 中,添加

    builder.Services.AddScoped<ICounterStateService, CounterStateService>();

Counter.razor

<p>Current count: @CounterService.CurrentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Increment</button>

@code 
    [Parameter]
    public CounterService CounterService  get; set; 

    private void IncrementCount()
    
        CounterService.CurrentCount++;
    

PageA.razor

@page "/pagea"
@inject ICounterStateService CounterStateService

<h3>Page A</h3>
<Counter CounterService='CounterStateService["A"]' />
<button class="btn btn-primary" @onclick='CounterStateService["A"].ResetCount'>Reset Count</button>

PageB.razor

@page "/pageb"
@inject ICounterStateService CounterStateService

<h3>Page B</h3>
<Counter CounterService='CounterStateService["B"]' />
<button class="btn btn-primary" @onclick='CounterStateService["B"].ResetCount'>Reset Count</button>

【问题讨论】:

使用相同的服务和接口并创建工厂服务来创建它们并将它们存储在具有名称的字典中。 这种状态服务听起来不像是共享的。如果每个组件只使用一个实例,为什么只注入构造。 【参考方案1】:

或者,这应该以其他方式完成吗?

是的。将这种使用模式烘焙到 Type 结构中不会很好地适应或扩展。如果您需要第三页,或者想让它动态化怎么办?

您可以使用包装服务和带有密钥的方案将状态绑定到组件:

public class CounterService   ...     // no need to register

public class CounterStateService  // register for injection


    private Dictionary <string, CounterService> stateLookup = new();

    public CounterService  this[string key] 
    
      if (! stateLookup.tryGetValue (key, out CounterService  service))
      
         service = new CounterService();
         stateLookup.Add(key, service);
      
      return service;
    

并像使用它

@page "/pagea"
@inject CounterStateService  CounterStateService

<h3>Page A</h3>
<Counter CounterService="CounterStateService["A"]" />

【讨论】:

Swift:检查来自同一类的 2 个对象是不是具有不同的值?

...布时间】:2020-08-2419:45:55【问题描述】:我在我的项目中使用swift。我有2个来自同一类的对象(例如来自MyClass类的对象A和对象B):classMyClass:NSObject 查看详情

Blazor 组件动态授权

】Blazor组件动态授权【英文标题】:Blazorcomponentdynamicauthorization【发布时间】:2021-09-0508:12:17【问题描述】:我正在尝试让Blazor身份验证为Razor页面/组件动态工作。我将举例说明我正在努力实现的目标......假设您有2个具有2个不... 查看详情

休眠。如何将条目添加到具有来自 Hibernate 中 2 个不同表的 2 个外键的表中?

】休眠。如何将条目添加到具有来自Hibernate中2个不同表的2个外键的表中?【英文标题】:Hibernate.HowcanIaddanentrytoatablethathas2foreignkeysfrom2differenttablesinHibernate?【发布时间】:2021-10-2802:12:48【问题描述】:我有三张桌子用户订购发... 查看详情

如何使用 Ajax 调用具有 2 个输入的 2 个不同的 URL

】如何使用Ajax调用具有2个输入的2个不同的URL【英文标题】:HowcanIcall2differentURLswith2inputsusingAjax【发布时间】:2018-06-2105:44:43【问题描述】:我该如何做简短的JS编码呢?我想用Ajax写value和data-sutun的结果。<inputautocomplete="off"dat... 查看详情

Blazor:如何存储页面状态(所有组件状态)?

】Blazor:如何存储页面状态(所有组件状态)?【英文标题】:Blazor:howtostorepagestate(allcomponentsstates)?【发布时间】:2021-04-1813:09:56【问题描述】:我有1个完整的页表组件(自定义,带有列过滤器、排序、动态加载、“无限”滚... 查看详情

如何连接具有 2 个不同维度的 2d 张量

】如何连接具有2个不同维度的2d张量【英文标题】:Howtoconcatenate2dtensorswith2differentdimensions【发布时间】:2021-04-0413:14:29【问题描述】:我想知道是否可以连接两个具有不同形状的不同pytorch张量。一个张量的形状为torch.Size([247,247... 查看详情

如何将来自 2 个不同数组的信息添加到文件中?

】如何将来自2个不同数组的信息添加到文件中?【英文标题】:Howdoiaddinfofrom2differentarraystoafile?【发布时间】:2017-06-0116:08:01【问题描述】:我有两个长度相同的数组,我想使用它们的内容。当我保存到json文件时,数组a和b的ind... 查看详情

具有来自两个不同模型的字段的 Django 表单

...型的多个字段。表单将仅包含模型中的部分字段,并且将使用清晰的表单进行布局。我的模型:classCompany(BaseModel):title=models.CharField(_(\'Co 查看详情

我如何将来自 3 个具有唯一 ID 的不同表的结果组合到 mysql 中

】我如何将来自3个具有唯一ID的不同表的结果组合到mysql中【英文标题】:howdoicombineresultsinmysqlfrom3differenttableswithuniqueid【发布时间】:2020-08-2821:07:40【问题描述】:这是我有3张桌子的情况,可以说cust_data,deposit_data,transaction_i... 查看详情

如何使用来自不同模块的两个具有相同名称的 AngularJS 服务?

】如何使用来自不同模块的两个具有相同名称的AngularJS服务?【英文标题】:HowtousetwoAngularJSserviceswithsamenamefromdifferentmodules?【发布时间】:2013-07-2514:14:34【问题描述】:假设我有两个AngularJS模块,例如foo和bar,它们都定义了一... 查看详情

ExtJS 3 多个状态网格(但具有不同的 stateIds)

...我的网格,它会覆盖Ext.grid.GridPanel我在我网站的2个地方使用了这个网格。我为他们生成了2个不同的stateId:构造函数:TasksGrid.superclass.constr 查看详情

MassTransit - 如何创建具有通用类型和 2 个不同消费者的交换主题

】MassTransit-如何创建具有通用类型和2个不同消费者的交换主题【英文标题】:MassTransit-Howtocreateanexchangetopicwithagenerictypeand2differentconsumers【发布时间】:2022-01-1803:22:48【问题描述】:我正在创建一个具有通用事件类型和2个不同消... 查看详情

如果我有 2 个具有相同视图但逻辑不同的 Angular 组件,如何正确构建代码?

】如果我有2个具有相同视图但逻辑不同的Angular组件,如何正确构建代码?【英文标题】:HowtostructurethecodecorrectlyifIhave2Angularcomponentsthathavethesameviewbutdifferentlogic?【发布时间】:2021-06-0917:34:52【问题描述】:我有这样一个情况,... 查看详情

如何使用来自不同位置的数据(分类变量)制作统计模型?

】如何使用来自不同位置的数据(分类变量)制作统计模型?【英文标题】:Howtomakeastatisticalmodelwithdatafromdifferentlocations(categoricalvariables)?【发布时间】:2021-12-3101:42:25【问题描述】:我正在帮助我的女朋友为她的硕士论文项目... 查看详情

2 个具有相同功能但变量名不同的 C++ 类 - 使用哪种模式?

...名和函数名是不同的,因为它们在各自的类中含义不同。如何 查看详情

使用来自 2 个不同表的字段创建表

】使用来自2个不同表的字段创建表【英文标题】:Creatingtableswithfieldsfrom2differenttables【发布时间】:2009-07-2204:34:19【问题描述】:我想创建一个表来存储来自两个不同表的值;从表1:cust_id(varchar2)、invoice_amt(float)来自表2:cust_id... 查看详情

如何使用 spring boot 插件 2.0.x 从一个具有不同依赖项的 gradle 项目生成 2 个 jars

】如何使用springboot插件2.0.x从一个具有不同依赖项的gradle项目生成2个jars【英文标题】:Howtogenerate2jarsfromonegradleprojectwithdifferentdependenciesusingsringbootplugin2.0.x【发布时间】:2019-03-2002:45:01【问题描述】:我正在尝试将我的项目迁移... 查看详情

如何通过 asyncTask 方法解析来自 2 个不同 URL 的数据

】如何通过asyncTask方法解析来自2个不同URL的数据【英文标题】:Howtoparsedatafrom2differentURLsbyasyncTaskmethod【发布时间】:2013-12-1221:54:36【问题描述】:我有一个从JSONURL获取数据的应用。它与一个URL完美配合,但我需要同时从两个JSO... 查看详情