由于是基于.net-core平台,所以,我们最好是基于IDistributedCache接口来实现。ASP.NET-CORE下的官方redis客户端实现是基于StackExchange的。但是官方提供的IDistributeCache接口中的方法只是增删改查,我们可以继续拓展,增加订阅/发布,消息队列,当然这些方法必须是基于底层的StackExchange相对应的方法来做的。
如果我们要实现自己的Redis客户端,同时不使用底层的StackExchange驱动,可以派生一个继承自IDistributedCache的接口,定义自己需要的方法,例如:

public interface IServiceStackRedisCache : IDistributedCache
{
    void Delete<T>(T item); // 删除
    void DeleteAll<T>(T item);
    T Get<T>(string id);
    IQueryable<T> GetAll<T>();
    IQueryable<T> GetAll<T>(string hash, string value);
    IQueryable<T> GetAll<T>(string hash, string value, Expression<Func<T, bool>> filter);
    long PublishMessage(string channel, object item);
    void Set<T>(T item);
    void Set<T>(T item, List<string> hash, List<string> value, string keyName);
    void Set<T>(T item, string hash, string value, string keyName);
    void SetAll<T>(List<T> listItems);
    void SetAll<T>(List<T> list, List<string> hash, List<string> value, string keyName);
    void SetAll<T>(List<T> list, string hash, string value, string keyName);
}

接口有了,接下来就是继承自接口的类,我们定义一个类来实现接口里的方法,例如:

using ServiceStack.Redis;

namespace Microsoft.Extensions.Caching.Redis
{
    public class ServiceStackRedisCache : IServiceStackRedisCache
    {
        private readonly IRedisClientsManager _redisManager;
        private readonly ServiceStackRedisCacheOptions _options;

        public ServiceStackRedisCache(IOptions<ServiceStackRedisCacheOptions> optionsAccessor)
        {
            if (optionsAccessor == null)
            {
                throw new ArgumentNullException(nameof(optionsAccessor));
            }

            _options = optionsAccessor.Value;

            var host = $"{_options.Password}@{_options.Host}:{_options.Port}";
            RedisConfig.VerifyMasterConnections = false;
            _redisManager = new RedisManagerPool(host);
        }
        #region Base

        public byte[] Get(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            using (var client = _redisManager.GetClient() as IRedisNativeClient)
            {
                if (client.Exists(key) == 1)
                {
                    return client.Get(key);
                }
            }
            return null;
        }

        public async Task<byte[]> GetAsync(string key)
        {
            return Get(key);
        }

        public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            using (var client = _redisManager.GetClient() as IRedisNativeClient)
            {
                var expireInSeconds = GetExpireInSeconds(options);
                if (expireInSeconds > 0)
                {
                    client.SetEx(key, expireInSeconds, value);
                    client.SetEx(GetExpirationKey(key), expireInSeconds, Encoding.UTF8.GetBytes(expireInSeconds.ToString()));
                }
                else
                {
                    client.Set(key, value);
                }
            }
        }

        public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options)
        {
            Set(key, value, options);
        }

        public void Refresh(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            using (var client = _redisManager.GetClient() as IRedisNativeClient)
            {
                if (client.Exists(key) == 1)
                {
                    var value = client.Get(key);
                    if (value != null)
                    {
                        var expirationValue = client.Get(GetExpirationKey(key));
                        if (expirationValue != null)
                        {
                            client.Expire(key, int.Parse(Encoding.UTF8.GetString(expirationValue)));
                        }
                    }
                }
            }
        }

        public async Task RefreshAsync(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            Refresh(key);
        }

        public void Remove(string key)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            using (var client = _redisManager.GetClient() as IRedisNativeClient)
            {
                client.Del(key);
            }
        }

        public async Task RemoveAsync(string key)
        {
            Remove(key);
        }

        private int GetExpireInSeconds(DistributedCacheEntryOptions options)
        {
            if (options.SlidingExpiration.HasValue)
            {
                return (int)options.SlidingExpiration.Value.TotalSeconds;
            }
            else if (options.AbsoluteExpiration.HasValue)
            {
                return (int)options.AbsoluteExpirationRelativeToNow.Value.TotalSeconds;
            }
            else
            {
                return 0;
            }
        }

        private string GetExpirationKey(string key)
        {
            return key + $"-{nameof(DistributedCacheEntryOptions)}";
        }
        #endregion
        #region data
        public T Get<T>(string id)
        {
            using (var redisClient = _redisManager.GetClient())
            {
                var redis = redisClient.As<T>();
                return redis.GetById(id.ToLower());
            }
        }

        public IQueryable<T> GetAll<T>()
        {
            using (var redisClient = _redisManager.GetClient())
            {
                var redis = redisClient.As<T>();
                return redis.GetAll().AsQueryable();
            }
        }

        public IQueryable<T> GetAll<T>(string hash, string value, Expression<Func<T, bool>> filter)
        {
            var filtered = _redisManager.GetClient().GetAllEntriesFromHash(hash).Where(c => c.Value.Equals(value, StringComparison.CurrentCultureIgnoreCase));
            var ids = filtered.Select(c => c.Key);

            var ret = _redisManager.GetClient().As<T>().GetByIds(ids).AsQueryable()
                                .Where(filter);

            return ret;
        }

        public IQueryable<T> GetAll<T>(string hash, string value)
        {
            var filtered = _redisManager.GetClient().GetAllEntriesFromHash(hash).Where(c => c.Value.Equals(value, StringComparison.CurrentCultureIgnoreCase));
            var ids = filtered.Select(c => c.Key);

            var ret = _redisManager.GetClient().As<T>().GetByIds(ids).AsQueryable();
            return ret;
        }

        public void Set<T>(T item)
        {
            using (var redisClient = _redisManager.GetClient())
            {
                var redis = redisClient.As<T>();
                redis.Store(item);
            }
        }

        public void Set<T>(T item, string hash, string value, string keyName)
        {
            Type t = item.GetType();
            PropertyInfo prop = t.GetProperty(keyName);

            _redisManager.GetClient().SetEntryInHash(hash, prop.GetValue(item).ToString(), value.ToLower());

            _redisManager.GetClient().As<T>().Store(item);
        }

        public void Set<T>(T item, List<string> hash, List<string> value, string keyName)
        {
            Type t = item.GetType();
            PropertyInfo prop = t.GetProperty(keyName);

            for (int i = 0; i < hash.Count; i++)
            {
                _redisManager.GetClient().SetEntryInHash(hash[i], prop.GetValue(item).ToString(), value[i].ToLower());
            }

            _redisManager.GetClient().As<T>().Store(item);
        }

        public void SetAll<T>(List<T> listItems)
        {
            using (var redisClient = _redisManager.GetClient())
            {
                var redis = redisClient.As<T>();
                redis.StoreAll(listItems);
            }
        }

        public void SetAll<T>(List<T> list, string hash, string value, string keyName)
        {
            foreach (var item in list)
            {
                Type t = item.GetType();
                PropertyInfo prop = t.GetProperty(keyName);

                _redisManager.GetClient().SetEntryInHash(hash, prop.GetValue(item).ToString(), value.ToLower());

                _redisManager.GetClient().As<T>().StoreAll(list);
            }
        }

        public void SetAll<T>(List<T> list, List<string> hash, List<string> value, string keyName)
        {
            foreach (var item in list)
            {
                Type t = item.GetType();
                PropertyInfo prop = t.GetProperty(keyName);

                for (int i = 0; i < hash.Count; i++)
                {
                    _redisManager.GetClient().SetEntryInHash(hash[i], prop.GetValue(item).ToString(), value[i].ToLower());
                }

                _redisManager.GetClient().As<T>().StoreAll(list);
            }
        }

        public void Delete<T>(T item)
        {
            using (var redisClient = _redisManager.GetClient())
            {
                var redis = redisClient.As<T>();
                redis.Delete(item);
            }
        }

        public void DeleteAll<T>(T item)
        {
            using (var redisClient = _redisManager.GetClient())
            {
                var redis = redisClient.As<T>();
                redis.DeleteAll();
            }
        }

        public long PublishMessage(string channel, object item)
        {
            var ret = _redisManager.GetClient().PublishMessage(channel, JsonConvert.SerializeObject(item));
            return ret;
        }

        #endregion
    }
}
View Code

相关文章:

  • 2022-12-23
  • 2021-08-13
  • 2022-12-23
  • 2022-12-23
  • 2021-11-13
  • 2021-08-26
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-03-02
  • 2021-06-02
  • 2021-10-07
相关资源
相似解决方案