diff --git a/src/BootstrapBlazor.Server/Extensions/ICacheEntryExtensions.cs b/src/BootstrapBlazor.Server/Extensions/ICacheEntryExtensions.cs
index c5fca810dd5..736a41d87d2 100644
--- a/src/BootstrapBlazor.Server/Extensions/ICacheEntryExtensions.cs
+++ b/src/BootstrapBlazor.Server/Extensions/ICacheEntryExtensions.cs
@@ -27,11 +27,13 @@ public static string GetExpiration(this ICacheEntry entry)
}
else if (entry.SlidingExpiration.HasValue)
{
- ret = $"Sliding: {entry.GetSlidingLeftTime().TotalSeconds:###}/{entry.SlidingExpiration.Value.TotalSeconds}";
+ var ts = entry.GetSlidingLeftTime();
+ ret = ts == TimeSpan.Zero ? "Expirated" : $"Sliding: {ts.TotalSeconds:###}/{entry.SlidingExpiration.Value.TotalSeconds}";
}
else if (entry.AbsoluteExpiration.HasValue)
{
- ret = $"Absolute: {entry.AbsoluteExpiration.Value}";
+ var ts = entry.GetAbsoluteLeftTime();
+ ret = ts == TimeSpan.Zero ? "Expirated" : $"Absolute: {ts.TotalSeconds:###}";
}
else if (entry.ExpirationTokens.Count != 0)
{
@@ -59,4 +61,14 @@ private static TimeSpan GetSlidingLeftTime(this ICacheEntry entry)
}
return ts;
}
+
+ private static TimeSpan GetAbsoluteLeftTime(this ICacheEntry entry)
+ {
+ var ts = entry.AbsoluteExpiration!.Value - DateTimeOffset.UtcNow;
+ if (ts < TimeSpan.Zero)
+ {
+ ts = TimeSpan.Zero;
+ }
+ return ts;
+ }
}
diff --git a/src/BootstrapBlazor/Extensions/ICacheEntryExtensions.cs b/src/BootstrapBlazor/Extensions/ICacheEntryExtensions.cs
index 925fefcf6fa..6bde1aaf3ca 100644
--- a/src/BootstrapBlazor/Extensions/ICacheEntryExtensions.cs
+++ b/src/BootstrapBlazor/Extensions/ICacheEntryExtensions.cs
@@ -40,4 +40,17 @@ public static class ICacheEntryExtensions
}
private static PropertyInfo? _lastAccessedProperty = null;
+
+ ///
+ /// Sets default sliding expiration if no expiration is configured
+ ///
+ internal static void SetDefaultSlidingExpiration(this ICacheEntry entry, TimeSpan offset)
+ {
+ if (entry.SlidingExpiration == null && entry.AbsoluteExpiration == null
+ && entry.AbsoluteExpirationRelativeToNow == null
+ && entry.Priority != CacheItemPriority.NeverRemove)
+ {
+ entry.SetSlidingExpiration(offset);
+ }
+ }
}
diff --git a/src/BootstrapBlazor/Options/BootstrapBlazorOptions.cs b/src/BootstrapBlazor/Options/BootstrapBlazorOptions.cs
index e0a1dabdf06..139868f135e 100644
--- a/src/BootstrapBlazor/Options/BootstrapBlazorOptions.cs
+++ b/src/BootstrapBlazor/Options/BootstrapBlazorOptions.cs
@@ -91,35 +91,40 @@ public class BootstrapBlazorOptions : IOptions
public TableSettings TableSettings { get; set; } = new();
///
- /// 获得/设置 Step 配置实例
+ /// 获得/设置 配置实例
///
public StepSettings StepSettings { get; set; } = new();
///
- /// 获得/设置 ConnectionHubOptions 配置 默认不为空
+ /// 获得/设置 配置 默认不为空
///
public ConnectionHubOptions ConnectionHubOptions { get; set; } = new();
///
- /// 获得/设置 WebClientOptions 配置 默认不为空
+ /// 获得/设置 配置 默认不为空
///
public WebClientOptions WebClientOptions { get; set; } = new();
///
- /// 获得/设置 IpLocatorOptions 配置 默认不为空
+ /// 获得/设置 配置 默认不为空
///
public IpLocatorOptions IpLocatorOptions { get; set; } = new();
///
- /// 获得/设置 ScrollOptions 配置 默认不为空
+ /// 获得/设置 配置 默认不为空
///
public ScrollOptions ScrollOptions { get; set; } = new();
///
- /// 获得/设置 ContextMenuOptions 配置 默认不为空
+ /// 获得/设置 配置 默认不为空
///
public ContextMenuOptions ContextMenuOptions { get; set; } = new();
+ ///
+ /// 获得/设置 CacheManagerOptions 配置 默认不为空
+ ///
+ public CacheManagerOptions CacheManagerOptions { get; set; } = new();
+
BootstrapBlazorOptions IOptions.Value => this;
///
diff --git a/src/BootstrapBlazor/Options/CacheManagerOptions.cs b/src/BootstrapBlazor/Options/CacheManagerOptions.cs
new file mode 100644
index 00000000000..af2a81ff2bd
--- /dev/null
+++ b/src/BootstrapBlazor/Options/CacheManagerOptions.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License
+// See the LICENSE file in the project root for more information.
+// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+
+namespace BootstrapBlazor.Components;
+
+///
+/// CacheManagerOptions 配置类
+///
+public class CacheManagerOptions
+{
+ ///
+ /// 获得/设置 是否开启 CacheManager 功能 默认 true 开启
+ ///
+ public bool Enable { get; set; } = true;
+
+ ///
+ /// 获得/设置 滑动缓存过期时间 默认 5 分钟
+ ///
+ public TimeSpan SlidingExpiration { get; set; } = TimeSpan.FromMinutes(5);
+
+ ///
+ /// 获得/设置 绝对缓存过期时间 默认 10 秒钟
+ ///
+ public TimeSpan AbsoluteExpiration { get; set; } = TimeSpan.FromSeconds(10);
+}
diff --git a/src/BootstrapBlazor/Services/CacheManager.cs b/src/BootstrapBlazor/Services/CacheManager.cs
index 74a03cf0c2b..90eca88ad94 100644
--- a/src/BootstrapBlazor/Services/CacheManager.cs
+++ b/src/BootstrapBlazor/Services/CacheManager.cs
@@ -30,6 +30,9 @@ internal class CacheManager : ICacheManager
[NotNull]
private static CacheManager? Instance { get; set; }
+ [NotNull]
+ private static BootstrapBlazorOptions? Options { get; set; }
+
private const string CacheKeyPrefix = "BootstrapBlazor";
///
@@ -42,6 +45,7 @@ public CacheManager(IServiceProvider provider, IMemoryCache memoryCache)
Provider = provider;
Cache = memoryCache;
Instance = this;
+ Options = Provider.GetRequiredService>().Value;
}
///
@@ -51,10 +55,7 @@ public TItem GetOrCreate(object key, Func factory) =>
{
var item = factory(entry);
- if (entry.SlidingExpiration == null && entry.AbsoluteExpiration == null && entry.Priority != CacheItemPriority.NeverRemove)
- {
- entry.SetSlidingExpiration(TimeSpan.FromMinutes(5));
- }
+ entry.SetDefaultSlidingExpiration(Options.CacheManagerOptions.SlidingExpiration);
return item;
})!;
@@ -65,10 +66,7 @@ public Task GetOrCreateAsync(object key, Func(TModel model, string fieldName)
{
if (type.Assembly.IsDynamic)
{
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(10));
+ entry.SetAbsoluteExpiration(Options.CacheManagerOptions.AbsoluteExpiration);
}
return LambdaExtensions.GetPropertyValueLambda(model, fieldName).Compile();
@@ -557,7 +555,7 @@ public static void SetPropertyValue(TModel model, string fieldNa
{
if (type.Assembly.IsDynamic)
{
- entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(10));
+ entry.SetAbsoluteExpiration(Options.CacheManagerOptions.AbsoluteExpiration);
}
return LambdaExtensions.SetPropertyValueLambda(model, fieldName).Compile();
});
diff --git a/test/UnitTest/Options/BootstrapBlazorOptionsTest.cs b/test/UnitTest/Options/BootstrapBlazorOptionsTest.cs
index 04a3e5d41b0..81420ae7474 100644
--- a/test/UnitTest/Options/BootstrapBlazorOptionsTest.cs
+++ b/test/UnitTest/Options/BootstrapBlazorOptionsTest.cs
@@ -103,4 +103,19 @@ public void Options_TableExportOptions()
Assert.Equal(",", exportOptions.ArrayDelimiter);
}
+
+ [Fact]
+ public void CacheManagerOptions_Ok()
+ {
+ var options = new BootstrapBlazorOptions();
+ Assert.NotNull(options.CacheManagerOptions);
+
+ options.CacheManagerOptions.Enable = true;
+ options.CacheManagerOptions.SlidingExpiration = TimeSpan.FromSeconds(1);
+ options.CacheManagerOptions.AbsoluteExpiration = TimeSpan.FromSeconds(1);
+
+ Assert.Equal(TimeSpan.FromSeconds(1), options.CacheManagerOptions.AbsoluteExpiration);
+ Assert.Equal(TimeSpan.FromSeconds(1), options.CacheManagerOptions.SlidingExpiration);
+ Assert.True(options.CacheManagerOptions.Enable);
+ }
}