如何在Blazor页面路由中使用强类型领域模型作为参数?
在Blazor中实现强类型领域ID的路由参数绑定
完全可以通过**自定义类型转换器(TypeConverter)**实现这个需求,这是Blazor原生支持的机制,无需在页面中手动转换,实现一次即可复用所有强类型ID。
实现步骤
1. 为强类型ID添加TypeConverter属性
给你的领域ID结构体标记[TypeConverter]属性,指定对应的转换器类型。如果有多个同类型基础值的ID(比如都是int类型的AccountId、OrderId),可以用泛型转换器复用逻辑。
单ID转换器示例
先定义AccountId并绑定转换器:
using System.ComponentModel; [TypeConverter(typeof(AccountIdConverter))] public readonly record struct AccountId(int Value);
然后实现AccountIdConverter:
public class AccountIdConverter : TypeConverter { // 支持从字符串转换为AccountId public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object? ConvertFrom(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { if (value is string str && int.TryParse(str, out var id)) { return new AccountId(id); } return base.ConvertFrom(context, culture, value); } // 支持从AccountId转换为字符串(用于生成路由链接等场景) public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) { return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); } public override object? ConvertTo(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, Type destinationType) { if (destinationType == typeof(string) && value is AccountId accountId) { return accountId.Value.ToString(); } return base.ConvertTo(context, culture, value, destinationType); } }
泛型转换器复用(推荐)
如果有多个基于int的强类型ID,定义一个通用接口和泛型转换器避免重复代码:
// 定义基础接口 public interface IIntId { int Value { get; } } // AccountId实现接口并绑定泛型转换器 [TypeConverter(typeof(IntIdConverter<AccountId>))] public readonly record struct AccountId(int Value) : IIntId; // OrderId同理 [TypeConverter(typeof(IntIdConverter<OrderId>))] public readonly record struct OrderId(int Value) : IIntId;
实现泛型转换器:
public class IntIdConverter<T> : TypeConverter where T : struct, IIntId { public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object? ConvertFrom(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object value) { if (value is string str && int.TryParse(str, out var id)) { // 通过反射创建强类型ID实例 return Activator.CreateInstance(typeof(T), id); } return base.ConvertFrom(context, culture, value); } public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) { return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); } public override object? ConvertTo(ITypeDescriptorContext? context, System.Globalization.CultureInfo? culture, object? value, Type destinationType) { if (destinationType == typeof(string) && value is IIntId intId) { return intId.Value.ToString(); } return base.ConvertTo(context, culture, value, destinationType); } }
2. 在Blazor组件中直接使用强类型参数
完成转换器实现后,你可以直接在组件中声明强类型参数,路由约束保持不变(或去掉约束也可,转换器会自动处理):
@page "/accounts/{accountId:int}" <h3>Account Details</h3> @code { [Parameter] public AccountId AccountId { get; set; } protected override void OnInitialized() { // 直接使用AccountId.Value即可,无需手动转换 Console.WriteLine($"Loading account with ID: {AccountId.Value}"); } }
原理说明
Blazor的路由参数绑定系统会自动检查参数类型是否带有TypeConverter属性,如果有,则使用转换器完成字符串(路由参数的原始类型)到强类型ID的转换,完全无需在页面中写额外的转换逻辑。
内容的提问来源于stack exchange,提问作者Paul Killick
相关产品推荐
相关产品推荐

