增量生成器简化Blazor内存中状态容器服务
AutoPageStateContainerGenerator
介绍
Blazor 的组件数据(或者说组件的属性),如果没有做特殊处理的话,在路由切换的时候就会丢失当前页面上的数据,不管是 Server 还是 WebAssembly,官方文档的推荐做法都是将数据抽出来当作一个服务,在页面中注入使用(内存中状态容器服务),而使用生成器,就可以很方便的完成这些功能,自动为 Razor 组件生成相应的数据容器。
使用
dotnet add package AutoPageStateContainerGenerator --version 0.0.5
StateContainerAttribute
在需要生成数据容器的组件上标注。
属性
| 名称 | 类型 | 说明 |
|---|---|---|
| Lifetime | Microsoft.Extensions.DependencyInjection.ServiceLifetime | 指定容器服务注入的生命周期 |
| Name | string? | 设置容器名称(用法) |
| Implements | Type? | 设置容器自定义实现类型(用法) |
SaveStateAttribute
标注需要保存的字段。
AddStateContainers
注入生成的数据容器
父类中使用
必须使用virtual属性
public partial class CounterParent : ComponentBase
{
[SaveState]
public virtual string? Type { get; set; } = "CounterParent";
public void CheckType()
{
Console.WriteLine(Type);
}
}
在其他地方使用内存数据容器
1. 直接从Ioc容器中获取,生成的类型为类型的全名StateContainer
2. 使用IStateContainerManager
设计目的:如果使用第一种方式,主要问题是类型名称太长,并且产生了依赖,所以就出现了IStateContainerManager
以Counter为例
public interface ICounter
{
// 假如我想在其他地方通过ICounter使用数据容器中的Name1
string? Name1 { get; set; }
}
[StateContainer(Name = "Counter", Implements = typeof(ICounter))]
public partial class Counter
{
[SaveState]
public partial string? Name1 { get; set; }
[SaveState]
public partial int Index { get; set; }
[SaveState(Init = "[]")]
public partial List<string> Values { get; set; }
}
在Home组件中使用Counter组件的数据容器
// 注入IStateContainerManager
[Inject, NotNull] IStateContainerManager? ContainerManager { get; set; }
ICounter? counter;
protected override void OnInitialized()
{
base.OnInitialized();
// 从IStateContainerManager中获取ICounter
counter = ContainerManager.GetStateContainer<ICounter>("Counter");
}
示例
Counter组件,不能直接在razor文件中添加该Attribute。
使用字段
[StateContainer(Name = "Counter", Implements = typeof(ICounter))]
public partial class Counter
{
[SaveState]
private string? name1;
[SaveState]
private int index;
[SaveState]
private List<string> values = [];
public string? Name2 { get; set; }
}
使用分部属性
[StateContainer(Name = "Counter", Implements = typeof(ICounter))]
public partial class Counter
{
[SaveState]
public partial string? Name1 { get; set; }
[SaveState]
public partial int Index { get; set; }
[SaveState(Init = "[]")]
public partial List<string> Values { get; set; }
public string? Name2 { get; set; }
}
生成的组件属性(分部属性)
using AutoPageStateContainerGenerator;
// <auto-generated/>
#pragma warning disable
#nullable enable
namespace Blazor.Test.Client.Pages;
/// <inheritdoc/>
partial class Counter
{
[global::Microsoft.AspNetCore.Components.InjectAttribute]
public Blazor_Test_Client_Pages_CounterStateContainer StateContainer { get; set; }
public override string? Type { get => StateContainer.Type; set => StateContainer.Type = value; }
public partial string? Name1 { get => StateContainer.Name1; set => StateContainer.Name1 = value; }
public partial int Index { get => StateContainer.Index; set => StateContainer.Index = value; }
public partial System.Collections.Generic.List<string> Values { get => StateContainer.Values; set => StateContainer.Values = value; }
}
生成的数据容器
using AutoPageStateContainerGenerator;
// <auto-generated/>
#pragma warning disable
#nullable enable
namespace Blazor.Test.Client.Pages;
[AutoPageStateContainerGenerator.GeneratedStateContainerAttribute(Lifetime = 0, Name = "Counter")]
[global::System.CodeDom.Compiler.GeneratedCode("AutoPageStateContainerGenerator.PageStateContainerGenerator", "0.0.4.0")]
/// <inheritdoc/>
public partial class Blazor_Test_Client_Pages_CounterStateContainer : AutoPageStateContainerGenerator.IGeneratedStateContainer, Blazor.Test.Client.Pages.ICounter
{
public event Action? OnChange;
private string? type = "CounterParent";
public string? Type
{
get
{
return type;
}
set
{
type = value;
NotifyStateChanged();
}
}
private string? name1;
public string? Name1
{
get
{
return name1;
}
set
{
name1 = value;
NotifyStateChanged();
}
}
private int index;
public int Index
{
get
{
return index;
}
set
{
index = value;
NotifyStateChanged();
}
}
private System.Collections.Generic.List<string> values = [];
public System.Collections.Generic.List<string> Values
{
get
{
return values;
}
set
{
values = value;
NotifyStateChanged();
}
}
private void NotifyStateChanged()
=> OnChange?.Invoke();
}

浙公网安备 33010602011771号