diff --git a/Maui.DataGrid/Collections/ConcurrentLRUCache.cs b/Maui.DataGrid/Collections/ConcurrentLRUCache.cs deleted file mode 100644 index 258cd56..0000000 --- a/Maui.DataGrid/Collections/ConcurrentLRUCache.cs +++ /dev/null @@ -1,217 +0,0 @@ -namespace Maui.DataGrid.Collections; - -using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; - -internal sealed class ConcurrentLRUCache : IDisposable, IDictionary - where TKey : notnull -{ - private readonly object _lock = new(); - - private readonly ConcurrentDictionary _cache; - private readonly ConcurrentDictionary _lruSet; - private int _capacity; - - public ConcurrentLRUCache(int capacity) - { - if (capacity <= 0) - { - throw new ArgumentException("Capacity must be greater than zero.", nameof(capacity)); - } - - _cache = new ConcurrentDictionary(); - _lruSet = new ConcurrentDictionary(); - - _capacity = capacity; - } - - public bool IsReadOnly => false; - - public ICollection Keys => _cache.Keys; - - public ICollection Values => _cache.Values; - - public int Count => _cache.Count; - - public TValue this[TKey key] - { - get => Get(key)!; - set => TryGetOrAdd(key, value); - } - - public bool Contains(TKey key) => _cache.ContainsKey(key); - - public TValue? Get(TKey key) - { - lock (_lock) - { - if (_cache.TryGetValue(key, out var value)) - { - _lruSet[key] = DateTime.UtcNow; - return value; - } - - return default; - } - } - - public TValue TryGetOrAdd(TKey key, TValue value) - { - lock (_lock) - { - if (_cache.TryGetValue(key, out var existingValue)) - { - _lruSet[key] = DateTime.UtcNow; - return existingValue; - } - - if (_cache.Count >= _capacity) - { - RemoveLeastRecentlyUsed(); - } - - _cache[key] = value; - _lruSet[key] = DateTime.UtcNow; - return value; - } - } - - public bool TryGetValue(TKey key, out TValue value) - { - lock (_lock) - { - if (_cache.TryGetValue(key, out value!)) - { - _lruSet[key] = DateTime.UtcNow; - return true; - } - - value = default!; - return false; - } - } - - public void Clear() - { - lock (_lock) - { - _cache.Clear(); - _lruSet.Clear(); - } - } - - public void SetCapacity(int newCapacity) - { - if (newCapacity <= 0) - { - throw new ArgumentException("Capacity must be greater than zero.", nameof(newCapacity)); - } - - lock (_lock) - { - _capacity = newCapacity; - - var oldestToNewest = _lruSet.OrderBy(kvp => kvp.Value).ToList(); - - foreach (var kvp in oldestToNewest) - { - if (_cache.Count <= _capacity) - { - return; - } - - if (_lruSet.TryRemove(kvp.Key, out _)) - { - _cache.TryRemove(kvp.Key, out _); - } - } - } - } - - public void Dispose() - { - Clear(); - } - - public IEnumerator> GetEnumerator() - { - return _cache.ToList().GetEnumerator(); - } - - public void Add(TKey key, TValue value) => TryGetOrAdd(key, value); - - public bool ContainsKey(TKey key) - { - return Contains(key); - } - - public bool Remove(TKey key) - { - lock (_lock) - { - if (_cache.TryRemove(key, out _)) - { - _lruSet.TryRemove(key, out _); - return true; - } - - return false; - } - } - - public void Add(KeyValuePair item) - { - Add(item.Key, item.Value); - } - - public bool Contains(KeyValuePair item) - { - return ContainsKey(item.Key) && EqualityComparer.Default.Equals(this[item.Key], item.Value); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - ((ICollection>)_cache).CopyTo(array, arrayIndex); - } - - public bool Remove(KeyValuePair item) - { - lock (_lock) - { - if (Contains(item)) - { - return Remove(item.Key); - } - - return false; - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - private void RemoveLeastRecentlyUsed() - { - var leastRecentlyUsedKey = default(TKey); - var oldestAccessTime = DateTime.MaxValue; - - foreach (var kvp in _lruSet) - { - if (kvp.Value < oldestAccessTime) - { - oldestAccessTime = kvp.Value; - leastRecentlyUsedKey = kvp.Key; - } - } - - if (leastRecentlyUsedKey != null && _lruSet.TryRemove(leastRecentlyUsedKey, out _)) - { - _cache.TryRemove(leastRecentlyUsedKey, out _); - } - } -} diff --git a/Maui.DataGrid/CompatibilitySuppressions.xml b/Maui.DataGrid/CompatibilitySuppressions.xml index 12720c6..f9f1c0f 100644 --- a/Maui.DataGrid/CompatibilitySuppressions.xml +++ b/Maui.DataGrid/CompatibilitySuppressions.xml @@ -1,46 +1,4 @@  - - CP0002 - F:Maui.DataGrid.DataGrid.CacheSizeProperty - lib/net8.0/Maui.DataGrid.dll - lib/net8.0/Maui.DataGrid.dll - true - - - CP0002 - F:Maui.DataGrid.DataGrid.CachingEnabledProperty - lib/net8.0/Maui.DataGrid.dll - lib/net8.0/Maui.DataGrid.dll - true - - - CP0002 - M:Maui.DataGrid.DataGrid.get_CacheSize - lib/net8.0/Maui.DataGrid.dll - lib/net8.0/Maui.DataGrid.dll - true - - - CP0002 - M:Maui.DataGrid.DataGrid.get_CachingEnabled - lib/net8.0/Maui.DataGrid.dll - lib/net8.0/Maui.DataGrid.dll - true - - - CP0002 - M:Maui.DataGrid.DataGrid.set_CacheSize(System.Int32) - lib/net8.0/Maui.DataGrid.dll - lib/net8.0/Maui.DataGrid.dll - true - - - CP0002 - M:Maui.DataGrid.DataGrid.set_CachingEnabled(System.Boolean) - lib/net8.0/Maui.DataGrid.dll - lib/net8.0/Maui.DataGrid.dll - true - - \ No newline at end of file + diff --git a/Maui.DataGrid/DataGrid.xaml.cs b/Maui.DataGrid/DataGrid.xaml.cs index 17e0566..1c750e9 100644 --- a/Maui.DataGrid/DataGrid.xaml.cs +++ b/Maui.DataGrid/DataGrid.xaml.cs @@ -115,18 +115,6 @@ public partial class DataGrid } }); - /// - /// Gets or sets a value indicating whether the DataGrid allows caching. - /// - public static readonly BindableProperty CachingEnabledProperty = - BindablePropertyExtensions.Create(false); - - /// - /// Gets or sets a value indicating whether the DataGrid allows caching. - /// - public static readonly BindableProperty CacheSizeProperty = - BindablePropertyExtensions.Create(DefaultCacheSize); - /// /// Gets or sets the Columns for the DataGrid. /// @@ -810,26 +798,6 @@ public IEnumerable ItemsSource set => SetValue(ItemsSourceProperty, value); } - /// - /// Gets or sets a value indicating whether caching is enabled in the DataGrid. - /// Default value is False. - /// - public bool CachingEnabled - { - get => (bool)GetValue(CachingEnabledProperty); - set => SetValue(CachingEnabledProperty, value); - } - - /// - /// Gets or sets a value indicating the size of the cache for the DataGrid. - /// Default value is 100000. - /// - public int CacheSize - { - get => (int)GetValue(CacheSizeProperty); - set => SetValue(CacheSizeProperty, value); - } - /// /// Gets or sets columns of the DataGrid. /// @@ -1384,11 +1352,11 @@ private IEnumerable GetSortedItems(IList unsortedItems, SortData { case SortingOrder.Ascendant: _ = columnToSort.SortingIcon.RotateTo(0); - items = unsortedItems.OrderBy(x => x.GetValueByPath(columnToSort.PropertyName, CachingEnabled, CacheSize)); + items = unsortedItems.OrderBy(x => x.GetValueByPath(columnToSort.PropertyName)); break; case SortingOrder.Descendant: _ = columnToSort.SortingIcon.RotateTo(180); - items = unsortedItems.OrderByDescending(x => x.GetValueByPath(columnToSort.PropertyName, CachingEnabled, CacheSize)); + items = unsortedItems.OrderByDescending(x => x.GetValueByPath(columnToSort.PropertyName)); break; case SortingOrder.None: return unsortedItems; diff --git a/Maui.DataGrid/DataGridColumn.cs b/Maui.DataGrid/DataGridColumn.cs index ab1c690..07dc2df 100644 --- a/Maui.DataGrid/DataGridColumn.cs +++ b/Maui.DataGrid/DataGridColumn.cs @@ -407,7 +407,7 @@ internal void InitializeDataType() } } - DataType = rowDataType?.GetPropertyTypeByPath(PropertyName, DataGrid.CachingEnabled, DataGrid.CacheSize); + DataType = rowDataType?.GetPropertyTypeByPath(PropertyName); } catch (Exception ex) when (ex is NotSupportedException or ArgumentNullException or InvalidCastException) diff --git a/Maui.DataGrid/Extensions/ReflectionExtensions.cs b/Maui.DataGrid/Extensions/ReflectionExtensions.cs index 38c2cb1..fb4d5f3 100644 --- a/Maui.DataGrid/Extensions/ReflectionExtensions.cs +++ b/Maui.DataGrid/Extensions/ReflectionExtensions.cs @@ -3,42 +3,18 @@ namespace Maui.DataGrid.Extensions; using System; using System.Diagnostics.CodeAnalysis; using System.Reflection; -using Maui.DataGrid.Collections; internal static class ReflectionExtensions { private const char PropertyOfOp = '.'; - private static readonly ConcurrentLRUCache ValueCache = new(DataGrid.DefaultCacheSize); - private static readonly ConcurrentLRUCache TypeCache = new(DataGrid.DefaultCacheSize); - - private static int _cacheSize = DataGrid.DefaultCacheSize; - - public static void SetCacheSize(int cacheSize) - { - Interlocked.Exchange(ref _cacheSize, cacheSize); - ReinitializeCaches(); - } - - public static object? GetValueByPath(this object obj, string path, bool useCaching, int cacheSize) + public static object? GetValueByPath(this object obj, string path) { if (obj == null || string.IsNullOrWhiteSpace(path)) { return null; } - if (useCaching && cacheSize != _cacheSize) - { - SetCacheSize(cacheSize); - } - - var cacheKey = useCaching ? $"{obj.GetHashCode()}_{obj.GetType().FullName}.{path}" : string.Empty; - - if (useCaching && ValueCache.TryGetValue(cacheKey, out var cachedValue)) - { - return cachedValue; - } - var result = obj; foreach (var token in path.Split(PropertyOfOp)) @@ -49,25 +25,15 @@ public static void SetCacheSize(int cacheSize) if (result == null) { - if (useCaching) - { - return ValueCache.TryGetOrAdd(cacheKey, null); - } - return null; } } - if (useCaching) - { - return ValueCache.TryGetOrAdd(cacheKey, result); - } - return result; } [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] - public static Type? GetPropertyTypeByPath([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] this Type type, string path, bool useCaching, int cacheSize) + public static Type? GetPropertyTypeByPath([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] this Type type, string path) { if (type == null) { @@ -79,18 +45,6 @@ public static void SetCacheSize(int cacheSize) return type; } - if (useCaching && cacheSize != _cacheSize) - { - SetCacheSize(cacheSize); - } - - var cacheKey = useCaching ? $"{type.GetHashCode()}_{type.FullName}.{path}" : string.Empty; - - if (useCaching && TypeCache.TryGetValue(cacheKey, out var cachedType)) - { - return cachedType; - } - var resultType = type; foreach (var token in path.Split(PropertyOfOp)) @@ -101,26 +55,10 @@ public static void SetCacheSize(int cacheSize) if (resultType == null) { - if (useCaching) - { - return TypeCache.TryGetOrAdd(cacheKey, null); - } - return null; } } - if (useCaching) - { - return TypeCache.TryGetOrAdd(cacheKey, resultType); - } - return resultType; } - - private static void ReinitializeCaches() - { - ValueCache.SetCapacity(_cacheSize); - TypeCache.SetCapacity(_cacheSize); - } }