-
-
Notifications
You must be signed in to change notification settings - Fork 381
feat(EmitHelper): use cache to reduce dynamic type creation. #7797
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
fb97eae
ebd87b8
fbf65d8
5eb79ce
3e392f5
3b03c5e
c9b2592
8fb0d8f
a326e6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,7 +40,7 @@ public class DataTableDynamicContext : DynamicObjectContext | |
| /// <para lang="zh">负责将 DataRow 与 Items 关联起来方便查找提高效率</para> | ||
| /// <para lang="en">Responsible for associating DataRow with Items to facilitate lookup and improve efficiency</para> | ||
| /// </summary> | ||
| private ConcurrentDictionary<Guid, (IDynamicObject DynamicObject, DataRow Row)> Caches { get; } = new(); | ||
| private ConcurrentDictionary<Guid, (IDynamicObject DynamicObject, DataRow Row)> _dataCache = new(); | ||
|
|
||
| /// <summary> | ||
| /// <para lang="zh">添加行回调委托</para> | ||
|
|
@@ -90,7 +90,20 @@ public DataTableDynamicContext(DataTable table, Action<DataTableDynamicContext, | |
| [ExcludeFromCodeCoverage] | ||
| Type CreateType() | ||
| { | ||
| var dynamicType = EmitHelper.CreateTypeByName($"BootstrapBlazor_{nameof(DataTableDynamicContext)}_{GetHashCode()}", cols, typeof(DataTableDynamicObject), OnColumnCreating); | ||
| // Emit 生成动态类 (使用缓存) | ||
| var columnNames = string.Join('|', table.Columns.Cast<DataColumn>().Select(static c => $"{c.ColumnName}:{c.DataType.FullName}")); | ||
| var cacheKey = $"BootstrapBlazor-{nameof(DataTableDynamicContext)}-{columnNames}"; | ||
|
ArgoZhang marked this conversation as resolved.
|
||
| var dynamicType = CacheManager.GetDynamicObjectTypeByName(cacheKey, cols, OnColumnCreating, out var cached); | ||
|
|
||
|
Comment on lines
+93
to
+97
|
||
| // 缓存命中时仍需调用回调以处理列属性 | ||
| if (cached && AddAttributesCallback != null) | ||
| { | ||
| foreach (var col in cols) | ||
| { | ||
| AddAttributesCallback?.Invoke(this, col); | ||
| } | ||
| } | ||
|
|
||
|
ArgoZhang marked this conversation as resolved.
|
||
| return dynamicType ?? throw new InvalidOperationException(); | ||
| } | ||
| } | ||
|
|
@@ -136,7 +149,7 @@ public override IEnumerable<IDynamicObject> GetItems() | |
|
|
||
| private List<IDynamicObject> BuildItems() | ||
| { | ||
| Caches.Clear(); | ||
| _dataCache.Clear(); | ||
| var ret = new List<IDynamicObject>(); | ||
| foreach (DataRow row in DataTable.Rows) | ||
| { | ||
|
|
@@ -155,7 +168,7 @@ private List<IDynamicObject> 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<IDynamicObject> 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<IDynamicObject> selectedItems) | |
| Items?.Insert(indexOfRow, dynamicObject); | ||
|
|
||
| // 缓存更新数据 | ||
| Caches.TryAdd(dynamicObject.DynamicObjectPrimaryKey, (dynamicObject, row)); | ||
| _dataCache.TryAdd(dynamicObject.DynamicObjectPrimaryKey, (dynamicObject, row)); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -252,15 +265,15 @@ public override async Task<bool> DeleteAsync(IEnumerable<IDynamicObject> 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; | ||
|
|
||
| // 删除数据源 | ||
| 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<bool> DeleteAsync(IEnumerable<IDynamicObject> 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; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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<object, Task<string?>> | |
|
|
||
| private static Func<TType, Task<string?>> InvokeFormatterAsync<TType>(Func<object?, Task<string?>> formatter) => new(v => formatter(v)); | ||
| #endregion | ||
|
|
||
| internal static Type? GetDynamicObjectTypeByName(string key, IEnumerable<ITableColumn> cols, Func<ITableColumn, IEnumerable<CustomAttributeBuilder>>? 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); | ||
| }); | ||
|
ArgoZhang marked this conversation as resolved.
Comment on lines
+773
to
+776
|
||
|
|
||
| // 是否从缓存中获取到的值 | ||
| cached = !created; | ||
| return type; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.