diff --git a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs index 9950d0bdd75..adadea24510 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Table/TablesDynamic.razor.cs @@ -47,6 +47,8 @@ private void CreateContext() DataTableDynamicContext = new DataTableDynamicContext(UserData, (context, col) => { var propertyName = col.GetFieldName(); + // 使用 Text 设置显示名称示例 + col.Text = FooLocalizer[propertyName]; if (propertyName == nameof(Foo.DateTime)) { context.AddRequiredAttribute(nameof(Foo.DateTime)); @@ -56,8 +58,6 @@ private void CreateContext() else if (propertyName == nameof(Foo.Name)) { context.AddRequiredAttribute(nameof(Foo.Name), FooLocalizer["Name.Required"]); - // 使用 Text 设置显示名称示例 - col.Text = FooLocalizer[nameof(Foo.Name)]; } else if (propertyName == nameof(Foo.Count)) { diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 0c5e8763a59..66d50a785ea 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 10.5.0-beta01 + 10.5.0-beta02 diff --git a/src/BootstrapBlazor/Dynamic/DataTableDynamicContext.cs b/src/BootstrapBlazor/Dynamic/DataTableDynamicContext.cs index 847d91b3183..63c002629fa 100644 --- a/src/BootstrapBlazor/Dynamic/DataTableDynamicContext.cs +++ b/src/BootstrapBlazor/Dynamic/DataTableDynamicContext.cs @@ -40,7 +40,7 @@ public class DataTableDynamicContext : DynamicObjectContext /// 负责将 DataRow 与 Items 关联起来方便查找提高效率 /// Responsible for associating DataRow with Items to facilitate lookup and improve efficiency /// - private ConcurrentDictionary Caches { get; } = new(); + private readonly ConcurrentDictionary _dataCache = new(); /// /// 添加行回调委托 @@ -90,7 +90,20 @@ public DataTableDynamicContext(DataTable table, Action().Select(static c => $"{c.ColumnName}:{c.DataType.FullName}")); + var cacheKey = $"BootstrapBlazor-{nameof(DataTableDynamicContext)}-{columnNames}"; + var dynamicType = CacheManager.GetDynamicObjectTypeByName(cacheKey, cols, OnColumnCreating, out var cached); + + // 缓存命中时仍需调用回调以处理列属性 + if (cached && AddAttributesCallback != null) + { + foreach (var col in cols) + { + AddAttributesCallback?.Invoke(this, col); + } + } + return dynamicType ?? throw new InvalidOperationException(); } } @@ -136,7 +149,7 @@ public override IEnumerable GetItems() private List BuildItems() { - Caches.Clear(); + _dataCache.Clear(); var ret = new List(); foreach (DataRow row in DataTable.Rows) { @@ -155,7 +168,7 @@ private List BuildItems() d.Row = row; d.DynamicObjectPrimaryKey = Guid.NewGuid(); - Caches.TryAdd(d.DynamicObjectPrimaryKey, (d, row)); + _dataCache.TryAdd(d.DynamicObjectPrimaryKey, (d, row)); ret.Add(d); } } @@ -203,7 +216,7 @@ public override async Task AddAsync(IEnumerable selectedItems) var indexOfRow = 0; var item = selectedItems.FirstOrDefault(); - if (item != null && Caches.TryGetValue(item.DynamicObjectPrimaryKey, out var c)) + if (item != null && _dataCache.TryGetValue(item.DynamicObjectPrimaryKey, out var c)) { indexOfRow = DataTable.Rows.IndexOf(c.Row); } @@ -232,7 +245,7 @@ public override async Task AddAsync(IEnumerable selectedItems) Items?.Insert(indexOfRow, dynamicObject); // 缓存更新数据 - Caches.TryAdd(dynamicObject.DynamicObjectPrimaryKey, (dynamicObject, row)); + _dataCache.TryAdd(dynamicObject.DynamicObjectPrimaryKey, (dynamicObject, row)); } } @@ -252,7 +265,7 @@ public override async Task DeleteAsync(IEnumerable items) var changed = false; foreach (var item in items) { - if (Caches.TryGetValue(item.DynamicObjectPrimaryKey, out var row)) + if (_dataCache.TryGetValue(item.DynamicObjectPrimaryKey, out var row)) { changed = true; @@ -260,7 +273,7 @@ public override async Task DeleteAsync(IEnumerable items) DataTable.Rows.Remove(row.Row); // 清理缓存 - Caches.TryRemove(item.DynamicObjectPrimaryKey, out _); + _dataCache.TryRemove(item.DynamicObjectPrimaryKey, out _); // 清理 Table 组件数据源 Items?.Remove(item); @@ -289,7 +302,7 @@ public override async Task DeleteAsync(IEnumerable items) private Task OnCellValueChanged(IDynamicObject item, ITableColumn column, object? val) { // 更新内部 DataRow - if (Caches.TryGetValue(item.DynamicObjectPrimaryKey, out var cacheItem)) + if (_dataCache.TryGetValue(item.DynamicObjectPrimaryKey, out var cacheItem)) { cacheItem.Row[column.GetFieldName()] = val; Items = null; diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs index 0d459357f23..400e72a2e7c 100644 --- a/src/BootstrapBlazor/Services/CacheManager.cs +++ b/src/BootstrapBlazor/Services/CacheManager.cs @@ -10,6 +10,7 @@ using System.Globalization; using System.Linq.Expressions; using System.Reflection; +using System.Reflection.Emit; #if NET8_0_OR_GREATER using System.Runtime.CompilerServices; @@ -764,4 +765,18 @@ public static object GetFormatterInvoker(Type type, Func> private static Func> InvokeFormatterAsync(Func> formatter) => new(v => formatter(v)); #endregion + + internal static Type? GetDynamicObjectTypeByName(string key, IEnumerable cols, Func>? creatingCallback, out bool cached) + { + var created = false; + var type = Instance.GetOrCreate(key, _ => + { + created = true; + return EmitHelper.CreateTypeByName($"BootstrapBlazor_{nameof(DataTableDynamicContext)}_{key}", cols, typeof(DataTableDynamicObject), creatingCallback); + }); + + // 是否从缓存中获取到的值 + cached = !created; + return type; + } }