From 9e37e80fd0c6089f9e4fb4f5879b003a2c276a1c Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 5 Mar 2025 18:41:40 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20IsAutoInitiali?= =?UTF-8?q?zeModelProperty=20=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Table/Table.razor.Edit.cs | 14 ++++- .../Extensions/ObjectExtensions.cs | 58 ++++++++++++++----- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs index 33343ab736b..67d19bff5dc 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs @@ -294,18 +294,28 @@ private async Task InternalOnAddAsync() [Parameter] public Func? CreateItemCallback { get; set; } + /// + /// Get or sets Whether to automatically initialize model properties default value is false. + /// + [Parameter] + public bool IsAutoInitializeModelProperty { get; set; } + private TItem CreateTItem() => CreateItemCallback?.Invoke() ?? CreateInstance(); + private readonly string ErrorMessage = $"{typeof(TItem)} create instrance failed. Please provide {nameof(CreateItemCallback)} create the {typeof(TItem)} instance. {typeof(TItem)} 自动创建实例失败,请通过 {nameof(CreateItemCallback)} 回调方法手动创建实例"; + private TItem CreateInstance() { + TItem? item; try { - return ObjectExtensions.CreateInstanceWithCascade(); + item = ObjectExtensions.CreateInstanceWithCascade(IsAutoInitializeModelProperty); } catch (Exception ex) { - throw new InvalidOperationException($"{typeof(TItem)} missing new() method. Please provide {nameof(CreateItemCallback)} create the {typeof(TItem)} instance. {typeof(TItem)} 未提供无参构造函数 new() 请通过 {nameof(CreateItemCallback)} 回调方法创建实例", ex); + throw new InvalidOperationException(ErrorMessage, ex); } + return item ?? throw new InvalidOperationException(ErrorMessage); } /// diff --git a/src/BootstrapBlazor/Extensions/ObjectExtensions.cs b/src/BootstrapBlazor/Extensions/ObjectExtensions.cs index 637e0db9f6a..7fc68bd8bfd 100644 --- a/src/BootstrapBlazor/Extensions/ObjectExtensions.cs +++ b/src/BootstrapBlazor/Extensions/ObjectExtensions.cs @@ -242,20 +242,56 @@ internal static void Clone(this TModel source, TModel item) /// Creates an instance of a type and ensures all class-type properties are initialized. /// /// The type to create an instance of. + /// Whether to automatically initialize model properties default value is false. /// An instance of the specified type with initialized properties. - public static TItem CreateInstanceWithCascade() + public static TItem? CreateInstanceWithCascade(bool isAutoInitializeModelProperty = false) { - var instance = Activator.CreateInstance(); - instance!.EnsureInitialized(); + TItem? instance; + try + { + instance = Activator.CreateInstance(); + if (isAutoInitializeModelProperty) + { + instance.EnsureInitialized(isAutoInitializeModelProperty); + } + } + catch + { + throw; + } + return instance; + } + + private static object? CreateInstance(Type type, bool isAutoInitializeModelProperty = false) + { + object? instance; + try + { + instance = Activator.CreateInstance(type); + if (isAutoInitializeModelProperty) + { + instance.EnsureInitialized(); + } + } + catch + { + throw; + } return instance; } /// /// Ensures that all class-type properties of the instance are initialized. /// + /// Whether to automatically initialize model properties default value is false. /// The instance to initialize properties for. - private static void EnsureInitialized(this object instance) + private static void EnsureInitialized(this object? instance, bool isAutoInitializeModelProperty = false) { + if (instance is null) + { + return; + } + // Reflection performance needs to be optimized here foreach (var propertyInfo in instance.GetType().GetProperties().Where(p => p.PropertyType.IsClass && p.PropertyType != typeof(string))) { @@ -263,16 +299,12 @@ private static void EnsureInitialized(this object instance) var value = propertyInfo.GetValue(instance, null); if (value is null) { - var pv = CreateInstance(type); - propertyInfo.SetValue(instance, pv); + var pv = CreateInstance(type, isAutoInitializeModelProperty); + if (pv is not null) + { + propertyInfo.SetValue(instance, pv); + } } } } - - private static object? CreateInstance(Type type) - { - var instance = Activator.CreateInstance(type); - instance!.EnsureInitialized(); - return instance; - } } From 0df7e289f9aee628c7e4a05cb6e546150dae2e52 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 5 Mar 2025 18:41:49 +0800 Subject: [PATCH 2/7] chore: bump version 9.4.6 --- src/BootstrapBlazor/BootstrapBlazor.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 90a61c17663..e4ca825a58a 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 9.4.5 + 9.4.6 From f762aa5758981d320388cfd353428730b39c4a34 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 5 Mar 2025 18:41:58 +0800 Subject: [PATCH 3/7] =?UTF-8?q?test:=20=E5=A2=9E=E5=8A=A0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Extensions/ObjectExtensionsTest.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/UnitTest/Extensions/ObjectExtensionsTest.cs b/test/UnitTest/Extensions/ObjectExtensionsTest.cs index 74d6aeded7f..e47671c69fc 100644 --- a/test/UnitTest/Extensions/ObjectExtensionsTest.cs +++ b/test/UnitTest/Extensions/ObjectExtensionsTest.cs @@ -303,6 +303,19 @@ public void IsStatic_Ok() Assert.True(pi.IsStatic()); } + [Fact] + public void CreateInstanceWithCascade_Ok() + { + var exception = Assert.ThrowsAny(() => ObjectExtensions.CreateInstanceWithCascade(true)); + } + + private class MockComplexObject + { + public Foo? Foo { get; set; } + + public (string Name, int Count)[]? Test { get; set; } + } + private class MockStatic { private static int _test; From 45d2a4ccb7f54a1d36a56239820514de8c0e703e Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 5 Mar 2025 19:00:55 +0800 Subject: [PATCH 4/7] =?UTF-8?q?refactor:=20=E6=9B=B4=E6=96=B0=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs | 4 ++-- src/BootstrapBlazor/Extensions/ObjectExtensions.cs | 2 +- test/UnitTest/Extensions/ObjectExtensionsTest.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs index 67d19bff5dc..fa8b766812e 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs @@ -309,13 +309,13 @@ private TItem CreateInstance() TItem? item; try { - item = ObjectExtensions.CreateInstanceWithCascade(IsAutoInitializeModelProperty); + item = ObjectExtensions.CreateInstance(IsAutoInitializeModelProperty); } catch (Exception ex) { throw new InvalidOperationException(ErrorMessage, ex); } - return item ?? throw new InvalidOperationException(ErrorMessage); + return item!; } /// diff --git a/src/BootstrapBlazor/Extensions/ObjectExtensions.cs b/src/BootstrapBlazor/Extensions/ObjectExtensions.cs index 7fc68bd8bfd..2b65aa085ba 100644 --- a/src/BootstrapBlazor/Extensions/ObjectExtensions.cs +++ b/src/BootstrapBlazor/Extensions/ObjectExtensions.cs @@ -244,7 +244,7 @@ internal static void Clone(this TModel source, TModel item) /// The type to create an instance of. /// Whether to automatically initialize model properties default value is false. /// An instance of the specified type with initialized properties. - public static TItem? CreateInstanceWithCascade(bool isAutoInitializeModelProperty = false) + public static TItem? CreateInstance(bool isAutoInitializeModelProperty = false) { TItem? instance; try diff --git a/test/UnitTest/Extensions/ObjectExtensionsTest.cs b/test/UnitTest/Extensions/ObjectExtensionsTest.cs index e47671c69fc..e2d3ec0cd85 100644 --- a/test/UnitTest/Extensions/ObjectExtensionsTest.cs +++ b/test/UnitTest/Extensions/ObjectExtensionsTest.cs @@ -304,7 +304,7 @@ public void IsStatic_Ok() } [Fact] - public void CreateInstanceWithCascade_Ok() + public void CreateInstance_Ok() { var exception = Assert.ThrowsAny(() => ObjectExtensions.CreateInstanceWithCascade(true)); } From ca551f06fd13b560b6540bad8d74e485579cad3d Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 5 Mar 2025 19:01:02 +0800 Subject: [PATCH 5/7] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Components/TableTest.cs | 1 + test/UnitTest/Extensions/ObjectExtensionsTest.cs | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/UnitTest/Components/TableTest.cs b/test/UnitTest/Components/TableTest.cs index b20df021baa..54527fb6684 100644 --- a/test/UnitTest/Components/TableTest.cs +++ b/test/UnitTest/Components/TableTest.cs @@ -127,6 +127,7 @@ public async Task Items_Add(InsertRowMode insertMode, bool bind) { pb.AddChildContent>(pb => { + pb.Add(a => a.IsAutoInitializeModelProperty, true); pb.Add(a => a.Items, items); if (bind) { diff --git a/test/UnitTest/Extensions/ObjectExtensionsTest.cs b/test/UnitTest/Extensions/ObjectExtensionsTest.cs index e2d3ec0cd85..5e975234d4b 100644 --- a/test/UnitTest/Extensions/ObjectExtensionsTest.cs +++ b/test/UnitTest/Extensions/ObjectExtensionsTest.cs @@ -306,7 +306,11 @@ public void IsStatic_Ok() [Fact] public void CreateInstance_Ok() { - var exception = Assert.ThrowsAny(() => ObjectExtensions.CreateInstanceWithCascade(true)); + var exception = Assert.ThrowsAny(() => ObjectExtensions.CreateInstance(true)); + + var mi = typeof(ObjectExtensions).GetMethod("EnsureInitialized", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); + Assert.NotNull(mi); + mi.Invoke(null, [null, false]); } private class MockComplexObject From 832abe0eb97be21b4cf224716e5e5cf2ea94eab1 Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 5 Mar 2025 19:26:50 +0800 Subject: [PATCH 6/7] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/UnitTest/Extensions/ObjectExtensionsTest.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/UnitTest/Extensions/ObjectExtensionsTest.cs b/test/UnitTest/Extensions/ObjectExtensionsTest.cs index 5e975234d4b..90beda9ef93 100644 --- a/test/UnitTest/Extensions/ObjectExtensionsTest.cs +++ b/test/UnitTest/Extensions/ObjectExtensionsTest.cs @@ -311,6 +311,10 @@ public void CreateInstance_Ok() var mi = typeof(ObjectExtensions).GetMethod("EnsureInitialized", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); Assert.NotNull(mi); mi.Invoke(null, [null, false]); + + var instance = ObjectExtensions.CreateInstance(false); + Assert.NotNull(instance); + Assert.Null(instance.Test); } private class MockComplexObject From 9adb648d0ebf826814ba6b7b414bf3b3c2192f6c Mon Sep 17 00:00:00 2001 From: Argo Zhang Date: Wed, 5 Mar 2025 19:35:29 +0800 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20=E7=B2=BE=E7=AE=80=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/ObjectExtensions.cs | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/BootstrapBlazor/Extensions/ObjectExtensions.cs b/src/BootstrapBlazor/Extensions/ObjectExtensions.cs index 2b65aa085ba..d631022682c 100644 --- a/src/BootstrapBlazor/Extensions/ObjectExtensions.cs +++ b/src/BootstrapBlazor/Extensions/ObjectExtensions.cs @@ -246,36 +246,20 @@ internal static void Clone(this TModel source, TModel item) /// An instance of the specified type with initialized properties. public static TItem? CreateInstance(bool isAutoInitializeModelProperty = false) { - TItem? instance; - try + var instance = Activator.CreateInstance(); + if (isAutoInitializeModelProperty) { - instance = Activator.CreateInstance(); - if (isAutoInitializeModelProperty) - { - instance.EnsureInitialized(isAutoInitializeModelProperty); - } - } - catch - { - throw; + instance.EnsureInitialized(isAutoInitializeModelProperty); } return instance; } private static object? CreateInstance(Type type, bool isAutoInitializeModelProperty = false) { - object? instance; - try - { - instance = Activator.CreateInstance(type); - if (isAutoInitializeModelProperty) - { - instance.EnsureInitialized(); - } - } - catch + var instance = Activator.CreateInstance(type); + if (isAutoInitializeModelProperty) { - throw; + instance.EnsureInitialized(); } return instance; }