为C#项目Redis缓存的Get<T>方法重载添加过期时间
为Redis缓存提供器实现带超时的Get方法重载
我来帮你完成给Redis缓存添加过期功能的需求——通过重载Get<T>系列方法,让它支持接收超时值。下面是修改后的完整代码,关键改动处我都做了标注:
public async Task<T> GetAsync<T>(string key) { return await _cacheClient.Db0.GetAsync<T>(key).ConfigureAwait(false); } /// <summary> /// Fetch item from cache /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="key">Key identifier in cache</param> /// <returns>Cached item</returns> public T Get<T>(string key) { return AsyncHelper.RunSync(() => _cacheClient.Db0.GetAsync<T>(key)); } /// <summary> /// Fetch from cache, else execute operation and cache /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="key">Key identifier in cache</param> /// <param name="method">Method to execute</param> /// <param name="args">Method args</param> /// <returns></returns> public async Task<T> GetAsync<T>(string key, Delegate method, params object[] args) { T result = default(T); try { if (await _cacheClient.Db0.ExistsAsync(key).ConfigureAwait(false)) { return await _cacheClient.Db0.GetAsync<T>(key).ConfigureAwait(false); } else { result = ExecMethod<T>(method, args); await _cacheClient.Db0.AddAsync(key, result).ConfigureAwait(false); } } catch (Exception ex) { _logHandler.LogError($"Error fetching cache for key:{key}", ex); result = ExecMethod<T>(method, args); } return result; } /// <summary> /// Fetch from cache, else execute operation and cache /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="key">Key identifier in cache</param> /// <param name="method">Method to execute</param> /// <param name="args">Method args</param> /// <returns></returns> public T Get<T>(string key, Delegate method, params object[] args) { T result = default(T); try { if (AsyncHelper.RunSync(() => _cacheClient.Db0.ExistsAsync(key))) { result = AsyncHelper.RunSync(() => _cacheClient.Db0.GetAsync<T>(key)); } else { result = ExecMethod<T>(method, args); var added = AsyncHelper.RunSync(() => _cacheClient.Db0.AddAsync(key, result)); } } catch (Exception ex) { _logHandler.LogError($"Error fetching cache for key:{key}", ex); result = ExecMethod<T>(method, args); } return result; } // -------------------------- 新增带超时的重载方法 -------------------------- /// <summary> /// Fetch from cache, else execute operation and cache with specified expiry /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="key">Key identifier in cache</param> /// <param name="method">Method to execute</param> /// <param name="expiry">Cache expiration time</param> /// <param name="args">Method args</param> /// <returns></returns> public async Task<T> GetAsync<T>(string key, Delegate method, TimeSpan expiry, params object[] args) { T result = default(T); try { if (await _cacheClient.Db0.ExistsAsync(key).ConfigureAwait(false)) { return await _cacheClient.Db0.GetAsync<T>(key).ConfigureAwait(false); } else { result = ExecMethod<T>(method, args); // 关键改动:将过期时间传入AddAsync,实现缓存自动过期 await _cacheClient.Db0.AddAsync(key, result, expiry).ConfigureAwait(false); } } catch (Exception ex) { _logHandler.LogError($"Error fetching cache for key:{key}", ex); result = ExecMethod<T>(method, args); } return result; } /// <summary> /// Fetch from cache, else execute operation and cache with specified expiry /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="key">Key identifier in cache</param> /// <param name="method">Method to execute</param> /// <param name="expiry">Cache expiration time</param> /// <param name="args">Method args</param> /// <returns></returns> public T Get<T>(string key, Delegate method, TimeSpan expiry, params object[] args) { T result = default(T); try { if (AsyncHelper.RunSync(() => _cacheClient.Db0.ExistsAsync(key))) { result = AsyncHelper.RunSync(() => _cacheClient.Db0.GetAsync<T>(key)); } else { result = ExecMethod<T>(method, args); // 关键改动:同步方法中同样传入过期时间 var added = AsyncHelper.RunSync(() => _cacheClient.Db0.AddAsync(key, result, expiry)); } } catch (Exception ex) { _logHandler.LogError($"Error fetching cache for key:{key}", ex); result = ExecMethod<T>(method, args); } return result; } // 可选:如果需要Redis操作本身的超时控制(而非缓存数据过期),可以添加以下重载 /// <summary> /// Fetch item from cache with operation timeout /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="key">Key identifier in cache</param> /// <param name="timeout">Operation timeout limit</param> /// <returns>Cached item</returns> public async Task<T> GetAsync<T>(string key, TimeSpan timeout) { using var cts = new CancellationTokenSource(timeout); return await _cacheClient.Db0.GetAsync<T>(key, cts.Token).ConfigureAwait(false); } /// <summary> /// Fetch item from cache with operation timeout /// </summary> /// <typeparam name="T">Return Type</typeparam> /// <param name="key">Key identifier in cache</param> /// <param name="timeout">Operation timeout limit</param> /// <returns>Cached item</returns> public T Get<T>(string key, TimeSpan timeout) { return AsyncHelper.RunSync(() => GetAsync<T>(key, timeout)); }
核心改动说明:
- 缓存过期支持:重点给「缓存不存在时执行方法并缓存」的
GetAsync和Get方法添加了TimeSpan expiry参数,在调用AddAsync时传入该参数,让Redis自动管理缓存的过期时间。 - 操作超时控制(可选):如果你的需求是限制Redis操作本身的耗时(比如获取缓存时最多等1秒),可以使用新增的直接获取重载,通过
CancellationTokenSource实现超时控制。 - 性能优化:在异步方法中保留了
ConfigureAwait(false),避免不必要的上下文切换,提升异步代码性能。 - 兼容性:原有方法完全保留,新增的重载不会影响现有业务代码的调用。
内容的提问来源于stack exchange,提问作者Mohammed Ismail
相关产品推荐
相关产品推荐

