From ef471539bce6e2f68ea118d9224674e6f64f26af Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Sun, 7 Jun 2026 14:34:54 +0800 Subject: [PATCH] refactor(DisplayBase): optimize nullable data types --- src/BootstrapBlazor/Components/Display/DisplayBase.cs | 11 +++++++---- .../InputNumber/BootstrapInputNumber.razor.cs | 2 +- .../Components/Radio/RadioList.razor.cs | 4 ++-- .../Components/Radio/RadioListGeneric.razor.cs | 2 +- .../Components/Select/MultiSelect.razor.cs | 2 +- src/BootstrapBlazor/Extensions/TypeExtensions.cs | 4 ++-- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/BootstrapBlazor/Components/Display/DisplayBase.cs b/src/BootstrapBlazor/Components/Display/DisplayBase.cs index 9bbc9a865f1..68bdeb52928 100644 --- a/src/BootstrapBlazor/Components/Display/DisplayBase.cs +++ b/src/BootstrapBlazor/Components/Display/DisplayBase.cs @@ -27,10 +27,14 @@ public abstract class DisplayBase : BootstrapModuleComponentBase protected FieldIdentifier? FieldIdentifier { get; set; } /// - /// 获得/设置 泛型参数 TValue 可为空类型 Type 实例,为空时表示类型不可为空 - /// Gets or sets Generic Parameter TValue Nullable Type Instance. Null means type is not nullable + /// 获得 泛型参数 TValue 可为空类型 Type 实例,为空时表示类型不可为空 + /// Gets the underlying type of when it is ; otherwise . /// - protected Type? NullableUnderlyingType { get; set; } + /// + /// 每个封闭泛型类型只计算一次缓存为静态字段,避免热路径重复反射 + /// Cached once per closed generic type to avoid repeated reflection on hot paths. + /// + protected static readonly Type? NullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TValue)); /// /// 获得/设置 泛型参数 TValue 可为空类型 Type 实例 @@ -121,7 +125,6 @@ public override Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); - NullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TValue)); ValueType ??= NullableUnderlyingType ?? typeof(TValue); if (ValueExpression != null) diff --git a/src/BootstrapBlazor/Components/InputNumber/BootstrapInputNumber.razor.cs b/src/BootstrapBlazor/Components/InputNumber/BootstrapInputNumber.razor.cs index 7247bc67347..6a74774de51 100644 --- a/src/BootstrapBlazor/Components/InputNumber/BootstrapInputNumber.razor.cs +++ b/src/BootstrapBlazor/Components/InputNumber/BootstrapInputNumber.razor.cs @@ -213,7 +213,7 @@ private static TValue ParseValue(string value) private bool IsDecimalType() { // 检查是否允许带小数点数据类型 - var type = NullableUnderlyingType ?? typeof(TValue); + var type = ValueType; return type == typeof(float) || type == typeof(double) || type == typeof(decimal); } diff --git a/src/BootstrapBlazor/Components/Radio/RadioList.razor.cs b/src/BootstrapBlazor/Components/Radio/RadioList.razor.cs index 44be7d4d593..d5fc6ee9272 100644 --- a/src/BootstrapBlazor/Components/Radio/RadioList.razor.cs +++ b/src/BootstrapBlazor/Components/Radio/RadioList.razor.cs @@ -60,7 +60,7 @@ public partial class RadioList /// protected override void OnParametersSet() { - var t = NullableUnderlyingType ?? typeof(TValue); + var t = ValueType; if (t.IsEnum && Items == null) { Items = t.ToSelectList((NullableUnderlyingType != null && IsAutoAddNullItem) ? new SelectedItem("", NullItemText) : null); @@ -91,7 +91,7 @@ protected override void OnParametersSet() protected override bool TryParseValueFromString(string value, [MaybeNullWhen(false)] out TValue result, out string? validationErrorMessage) { var ret = false; - var t = NullableUnderlyingType ?? typeof(TValue); + var t = ValueType; result = default; if (t == typeof(SelectedItem)) { diff --git a/src/BootstrapBlazor/Components/Radio/RadioListGeneric.razor.cs b/src/BootstrapBlazor/Components/Radio/RadioListGeneric.razor.cs index c7e1aedc168..a3982ba4062 100644 --- a/src/BootstrapBlazor/Components/Radio/RadioListGeneric.razor.cs +++ b/src/BootstrapBlazor/Components/Radio/RadioListGeneric.razor.cs @@ -128,7 +128,7 @@ protected override void OnParametersSet() Color = Color.Primary; } - var t = NullableUnderlyingType ?? typeof(TValue); + var t = ValueType; if (t.IsEnum && Items == null) { Items = t.ToSelectList((NullableUnderlyingType != null && IsAutoAddNullItem) ? new SelectedItem(default!, NullItemText) : null); diff --git a/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs b/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs index abe6d5b2945..46387fbd94e 100644 --- a/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs +++ b/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs @@ -578,7 +578,7 @@ private void ResetItems() } else { - innerType = NullableUnderlyingType ?? type; + innerType = ValueType; } if (innerType.IsEnum) { diff --git a/src/BootstrapBlazor/Extensions/TypeExtensions.cs b/src/BootstrapBlazor/Extensions/TypeExtensions.cs index 937bc9e3c2a..d8e3dbfbb96 100644 --- a/src/BootstrapBlazor/Extensions/TypeExtensions.cs +++ b/src/BootstrapBlazor/Extensions/TypeExtensions.cs @@ -58,7 +58,7 @@ void EnsureNoAuthenticationSchemeSpecified() /// /// 获得唯一类型名称方法 - /// Gets唯一type名称方法 + /// Gets a unique type name /// /// public static string GetUniqueTypeName(this Type type) => type.IsCollectible @@ -68,7 +68,7 @@ public static string GetUniqueTypeName(this Type type) => type.IsCollectible /// /// 通过 typeName 参数安全获取 Type 实例 - /// 通过 typeName 参数安全获取 Type instance + /// Gets a Type instance safely from the typeName parameter /// /// public static Type? GetSafeType(string? typeName)