基于Asp.net Core 3.1实现的Redis及MemoryCache缓存助手CacheHelper

注:下面涉及的代码文件可查看我的LessSharp框架Github

 

很久很久之前,这个关于Redis缓存的博客一直没空写,今天总算有点时间了。

 

一开始我是按微软官网文档那样配置的,然后发现这也太简单了,不止配置简单,连使用都这么简单,简单得有点过分。如下图所示,它是基于IDistributedCache接口注入的

这么简单,怎么玩,我连判断某个key值存不存在都没办法。

 

当然了。绝对不是这么简单的。更高级的用法如下,要引入Microsoft.Extensions.Caching.StackExchangeRedis包

ConnectionMultiplexer connection = ConnectionMultiplexer.Connect("127.0.0.1:6379");
IDatabase cache = connection.GetDatabase(0);
cache.HashSet("key", "hashKey", "value");
cache.SetAdd("key2", "value");

 

那要怎么用在系统里呢,当然直接使用IDatabase也可以,但不够优雅,而且我还想通过配置文件,来决定是否启用Redis,如果不启用的话,就使用MemoryCache。非常好。想法有了。

先定义一个接口ICacheHelper,这是用来注入的接口,我暂时只定义了string类型跟hash类型的缓存方法

复制代码
public interface ICacheHelper
{
    bool Exists(string key);

    void Set<T>(string key, T value);

    T Get<T>(string key);

    void Delete(string key);


    void Expire(string key, DateTime dateTime);
    void Expire(string key, TimeSpan timeSpan);

    void HashSet(string key, string hashKey, object hashValue);
    T HashGet<T>(string key, string hashKey);

    bool HashExists(string key, string hashKey);

    void HashDelete(string key, string hashKey);
}
复制代码

 

然后用Redis实现这个接口,RedisCacheHelper类

复制代码
/// <summary>
/// Redis助手
/// </summary>
public class RedisCacheHelper : ICacheHelper
{
    public IDatabase _cache;

    private ConnectionMultiplexer _connection;

    private readonly string _instance;
    public RedisCacheHelper(RedisCacheOptions options, int database = 0)
    {
        _connection = ConnectionMultiplexer.Connect(options.Configuration);
        _cache = _connection.GetDatabase(database);
        _instance = options.InstanceName;
    }

    public bool Exists(string key)
    {
        return _cache.KeyExists(_instance + key);
    }

    public void Set<T>(string key, T value)
    {
        _cache.StringSet(_instance + key, CommonHelper.ObjectToJsonString(value));
    }

    public T Get<T>(string key)
    {
        return CommonHelper.JsonStringToObject<T>(_cache.StringGet(_instance + key));
    }

    public void Delete(string key)
    {
        _cache.KeyDelete(_instance + key);
    }

    public void Expire(string key, DateTime dateTime)
    {
        _cache.KeyExpire(_instance + key, dateTime);
    }
    public void Expire(string key, TimeSpan timeSpan)
    {
        _cache.KeyExpire(_instance + key, timeSpan);
    }
    public void HashSet(string key, string hashKey, object hashValue)
    {
        string value = CommonHelper.ObjectToJsonString(hashValue);
        _cache.HashSet(_instance + key, hashKey, value);
    }

    public T HashGet<T>(string key, string hashKey)
    {
        var value = _cache.HashGet(_instance + key, hashKey);
        return CommonHelper.JsonStringToObject<T>(value);
    }

    public object HashGet(string key, string hashKey, Type type)
    {
        var value = _cache.HashGet(_instance + key, hashKey);
        return CommonHelper.JsonStringToObject(value, type);
    }

    public bool HashExists(string key, string hashKey)
    {
        return _cache.HashExists(_instance + key, hashKey);
    }

    public void HashDelete(string key, string hashKey)
    {
        _cache.HashDelete(_instance + key, hashKey);
    }
}
复制代码

 

再用MemoryCache实现接口,MemoryCacheHelper类

复制代码
/// <summary>
/// 缓存助手
/// </summary>
public class MemoryCacheHelper : ICacheHelper
{
    private readonly IMemoryCache _cache;
    public MemoryCacheHelper(IMemoryCache cache)
    {
        _cache = cache;
    }

    public bool Exists(string key)
    {
        return _cache.TryGetValue(key, out _);
    }

    public T Get<T>(string key)
    {
        return _cache.Get<T>(key);
    }

    public void Delete(string key)
    {
        _cache.Remove(key);
    }

    public void Set<T>(string key, T value)
    {
        _cache.Set(key, value);
    }
    public void Expire(string key, DateTime dateTime)
    {
        var value = _cache.Get(key);
        _cache.Set(key, value, dateTime);
    }

    public void Expire(string key, TimeSpan timeSpan)
    {
        var value = _cache.Get(key);
        _cache.Set(key, value, timeSpan);
    }
    public void HashSet(string key, string hashKey, object hashValue)
    {
        var hash = _cache.Get<Dictionary<string, object>>(key);
        if (hash.ContainsKey(hashKey))
        {
            hash[key] = hashValue;
        }
        else
        {
            hash.Add(hashKey, hashValue);
        }
        _cache.Set<Dictionary<string, object>>(key, hash);
    }

    public T HashGet<T>(string key, string hashKey)
    {
        var hash = _cache.Get<Dictionary<string, object>>(key);
        if (hash.ContainsKey(hashKey))
        {
            return (T)hash[hashKey];
        }
        else
        {
            return default(T);
        }
    }

    public bool HashExists(string key, string hashKey)
    {
        var hash = _cache.Get<Dictionary<string, object>>(key);
        return hash.ContainsKey(hashKey);
    }



    public void HashDelete(string key, string hashKey)
    {
        var hash = _cache.Get<Dictionary<string, object>>(key);
        if (hash.ContainsKey(hashKey))
        {
            hash.Remove(hashKey);
        }
    }
}
复制代码

 

实现类都有了,那现在就来实现根据配置值来决定是否使用Redis还是MemoryCache,先在appsettings.json里添加这个配置值,当Enable为false时,就不启用Redis,使用MemoryCache,Connection是Redis的连接字符串,InstanceName是缓存的前缀,Database是使用哪个数据库

"Redis": {
    "Enable": true,
    "Connection": "127.0.0.1:6379",
    "InstanceName": "LessSharp:",
    "Database": 0
  }

再定义一个选项类 RedisOption

public class RedisOption
{
    public bool Enable { get; set; }        
    public string Connection { get; set; }
    public string InstanceName { get; set; }
    public int Database { get; set; }
}

然后在Startup.cs类里的ConfigureServices里根据配置值进行注入

复制代码
var RedisConfiguration = Configuration.GetSection("Redis");
services.Configure<RedisOption>(RedisConfiguration);
RedisOption redisOption = RedisConfiguration.Get<RedisOption>();
if (redisOption != null && redisOption.Enable)
{
    var options = new RedisCacheOptions
    {
        InstanceName = redisOption.InstanceName,
        Configuration = redisOption.Connection
     };
     var redis = new RedisCacheHelper(options, redisOption.Database);
     services.AddSingleton(redis);
     services.AddSingleton<ICacheHelper>(redis);
}
else
{
      services.AddMemoryCache();
      services.AddScoped<ICacheHelper, MemoryCacheHelper>();
}
复制代码

OK,测试后完美

 

posted on   菜工  阅读(1579)  评论(1编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示