diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 7fa0a472304..d77361a2ee0 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@ - 8.10.2-beta01 + 8.10.2-beta02 diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs index 68a1b7bb729..0d3acf7326a 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs @@ -304,6 +304,14 @@ private TItem CreateTItem() return item; } + /// + /// 获得/设置 新建搜索模型回调方法 默认 null 未设置时先 尝试使用 回调,再使用默认无参构造函数创建 + /// + [Parameter] + public Func? CreateSearchModelCallback { get; set; } + + private TItem CreateSearchModel() => CreateSearchModelCallback?.Invoke() ?? CreateTItem(); + /// /// 单选模式下选择行时调用此方法 /// diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.Search.cs b/src/BootstrapBlazor/Components/Table/Table.razor.Search.cs index 7088f29a28d..5598899dcc8 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.Search.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.Search.cs @@ -139,7 +139,7 @@ protected async Task ResetSearchClick() } else if (SearchTemplate == null) { - Utility.Reset(SearchModel, CreateTItem()); + Utility.Reset(SearchModel, CreateSearchModel()); } PageIndex = 1; @@ -246,7 +246,7 @@ protected IEnumerable GetCustomerSearches() protected List GetAdvanceSearches() { var searches = new List(); - if (ShowAdvancedSearch && CustomerSearchModel == null && SearchModel != null) + if (ShowAdvancedSearch && CustomerSearchModel == null) { var callback = GetAdvancedSearchFilterCallback ?? new Func?>((p, model) => { diff --git a/src/BootstrapBlazor/Components/Table/Table.razor.cs b/src/BootstrapBlazor/Components/Table/Table.razor.cs index ad3f66d870e..010f55aeaf4 100644 --- a/src/BootstrapBlazor/Components/Table/Table.razor.cs +++ b/src/BootstrapBlazor/Components/Table/Table.razor.cs @@ -859,7 +859,7 @@ private void OnInitParameters() TreeNodeLoadingIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableTreeNodeLoadingIcon); AdvancedSortButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableAdvancedSortButtonIcon); - SearchModel ??= CreateTItem(); + SearchModel ??= CreateSearchModel(); } /// diff --git a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs index 1dcf2fbae60..ffa34608a94 100644 --- a/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs +++ b/src/BootstrapBlazor/Components/ValidateForm/ValidateForm.razor.cs @@ -632,13 +632,6 @@ public void NotifyFieldChanged(in FieldIdentifier fieldIdentifier, object? value OnFieldValueChanged?.Invoke(fieldIdentifier.FieldName, value); } - //private readonly List _invalidComponents = []; - - //internal void AddValidationComponent(string id) - //{ - // _invalidComponents.Add(id); - //} - /// /// 获取 当前表单值改变的属性集合 /// diff --git a/src/BootstrapBlazor/Extensions/TypeExtensions.cs b/src/BootstrapBlazor/Extensions/TypeExtensions.cs index ccefaf184d5..d175ff26f66 100644 --- a/src/BootstrapBlazor/Extensions/TypeExtensions.cs +++ b/src/BootstrapBlazor/Extensions/TypeExtensions.cs @@ -10,9 +10,9 @@ namespace BootstrapBlazor.Components; internal static class TypeExtensions { - public static PropertyInfo? GetPropertyByName(this Type type, string propertyName) => type.GetRuntimeProperties().FirstOrDefault(p => p.Name == propertyName); + public static PropertyInfo? GetPropertyByName(this Type type, string propertyName) => CacheManager.GetRuntimeProperties(type).Find(p => p.Name == propertyName); - public static FieldInfo? GetFieldByName(this Type type, string fieldName) => type.GetRuntimeFields().FirstOrDefault(p => p.Name == fieldName); + public static FieldInfo? GetFieldByName(this Type type, string fieldName) => CacheManager.GetRuntimeFields(type).Find(p => p.Name == fieldName); public static async Task IsAuthorizedAsync(this Type type, Task? authenticateState, IAuthorizationPolicyProvider? authorizePolicy, IAuthorizationService? authorizeService, object? resource = null) { diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index 52ac65d1ae7..3358cb916a3 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -720,4 +720,36 @@ public static object GetFormatterInvoker(Type type, Func> private static Func> InvokeFormatterAsync(Func> formatter) => new(v => formatter(v)); #endregion + + #region TypeExtensions + /// + /// 通过指定类型获得所有属性信息 + /// + /// + /// + public static List GetRuntimeProperties(Type type) + { + var cacheKey = $"{nameof(GetRuntimeProperties)}-{type.GetUniqueTypeName()}"; + return Instance.GetOrCreate(cacheKey, entry => + { + entry.SetDynamicAssemblyPolicy(type); + return type.GetRuntimeProperties().ToList(); + }); + } + + /// + /// 通过指定类型获得所有字段信息 + /// + /// + /// + public static List GetRuntimeFields(Type type) + { + var cacheKey = $"{nameof(GetRuntimeFields)}-{type.GetUniqueTypeName()}"; + return Instance.GetOrCreate(cacheKey, entry => + { + entry.SetDynamicAssemblyPolicy(type); + return type.GetRuntimeFields().ToList(); + })!; + } + #endregion } diff --git a/src/BootstrapBlazor/Utils/Utility.cs b/src/BootstrapBlazor/Utils/Utility.cs index 7e7dc4925f0..d85523777c4 100644 --- a/src/BootstrapBlazor/Utils/Utility.cs +++ b/src/BootstrapBlazor/Utils/Utility.cs @@ -213,13 +213,13 @@ public static class Utility /// public static void Reset(TModel source, TModel model) where TModel : class { - var v = model; + var modelType = model.GetType(); foreach (var pi in source.GetType().GetRuntimeProperties().Where(p => p.IsCanWrite())) { - var pInfo = v.GetType().GetPropertyByName(pi.Name); + var pInfo = modelType.GetPropertyByName(pi.Name); if (pInfo != null) { - pi.SetValue(source, pInfo.GetValue(v)); + pi.SetValue(source, pInfo.GetValue(model)); } } } diff --git a/test/UnitTest/Components/TableTest.cs b/test/UnitTest/Components/TableTest.cs index 09a30ebd908..d778ae52c08 100644 --- a/test/UnitTest/Components/TableTest.cs +++ b/test/UnitTest/Components/TableTest.cs @@ -3838,6 +3838,14 @@ public async Task CustomerSearchTemplate_Ok() var resetButton = cut.Find(".fa-trash-can"); await cut.InvokeAsync(() => resetButton.Click()); Assert.Null(searchModel.Name); + + var table = cut.FindComponent>(); + table.SetParametersAndRender(pb => + { + pb.Add(a => a.ShowAdvancedSearch, false); + }); + await cut.InvokeAsync(() => resetButton.Click()); + Assert.Null(searchModel.Name); } [Fact] @@ -3849,7 +3857,6 @@ public void SearchTemplate_Ok() pb.AddChildContent>(pb => { pb.Add(a => a.ShowSearch, true); - pb.Add(a => a.SearchModel, new Foo()); pb.Add(a => a.SearchMode, SearchMode.Top); pb.Add(a => a.RenderMode, TableRenderMode.Table); pb.Add(a => a.SearchTemplate, foo => builder => builder.AddContent(0, "test_SearchTemplate")); @@ -3863,8 +3870,17 @@ public void SearchTemplate_Ok() }); }); }); - cut.Contains("test_SearchTemplate"); + + var table = cut.FindComponent>(); + Assert.NotNull(table.Instance.SearchModel); + + table.SetParametersAndRender(pb => + { + pb.Add(a => a.SearchModel, null); + pb.Add(a => a.CreateSearchModelCallback, () => new Foo()); + }); + Assert.NotNull(table.Instance.SearchModel); } [Fact] diff --git a/test/UnitTest/Extensions/IQueryableExtensionsTest.cs b/test/UnitTest/Extensions/IQueryableExtensionsTest.cs index cbce7e00b65..c4a1d1b67ee 100644 --- a/test/UnitTest/Extensions/IQueryableExtensionsTest.cs +++ b/test/UnitTest/Extensions/IQueryableExtensionsTest.cs @@ -4,7 +4,7 @@ namespace UnitTest.Extensions; -public class IQueryableExtensionsTest +public class IQueryableExtensionsTest : BootstrapBlazorTestBase { [Fact] public void Where_Ok() @@ -28,8 +28,8 @@ public void Sort_Ok() new() { Name = "Test2" } }.AsQueryable(); - Assert.Equal("Test2", foos.Sort("Name", SortOrder.Desc, true).First().Name); - Assert.Equal("Test1", foos.Sort("Name", SortOrder.Desc, false).First().Name); + Assert.Equal("Test2", foos.Sort("Name", SortOrder.Desc, true).First().Name); + Assert.Equal("Test1", foos.Sort("Name", SortOrder.Desc, false).First().Name); } [Fact] diff --git a/test/UnitTest/Extensions/LambadaExtensionsTest.cs b/test/UnitTest/Extensions/LambadaExtensionsTest.cs index c7de7eda78d..725911582ac 100644 --- a/test/UnitTest/Extensions/LambadaExtensionsTest.cs +++ b/test/UnitTest/Extensions/LambadaExtensionsTest.cs @@ -8,7 +8,7 @@ namespace UnitTest.Extensions; -public class LambadaExtensionsTest +public class LambadaExtensionsTest : BootstrapBlazorTestBase { [Fact] public void GetFilterFunc_Null() diff --git a/test/UnitTest/Extensions/ObjectExtensionsTest.cs b/test/UnitTest/Extensions/ObjectExtensionsTest.cs index 0858051c94a..f0674fb47dc 100644 --- a/test/UnitTest/Extensions/ObjectExtensionsTest.cs +++ b/test/UnitTest/Extensions/ObjectExtensionsTest.cs @@ -7,7 +7,7 @@ namespace UnitTest.Extensions; -public class ObjectExtensionsTest +public class ObjectExtensionsTest : BootstrapBlazorTestBase { [Theory] [InlineData(null, "")] diff --git a/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs b/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs index 88c37c2930f..1e6e67a491b 100644 --- a/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs +++ b/test/UnitTest/Extensions/QueryPageOptionsExtensionsTest.cs @@ -4,7 +4,7 @@ namespace UnitTest.Extensions; -public class QueryPageOptionsExtensionsTest +public class QueryPageOptionsExtensionsTest : BootstrapBlazorTestBase { private readonly Foo[] _foos; diff --git a/test/UnitTest/Performance/ReflectionTest.cs b/test/UnitTest/Performance/ReflectionTest.cs index 55cf5187730..1d5395430f9 100644 --- a/test/UnitTest/Performance/ReflectionTest.cs +++ b/test/UnitTest/Performance/ReflectionTest.cs @@ -6,7 +6,7 @@ namespace UnitTest.Performance; -public class ReflectionTest(ITestOutputHelper logger) +public class ReflectionTest(ITestOutputHelper logger) : BootstrapBlazorTestBase { private ITestOutputHelper Logger { get; } = logger;