zoukankan      html  css  js  c++  java
  • asp.net core 上使用redis探索(3)--redis示例demo

    由于是基于.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

    在这里我们使用ServiceStack来作为底层redis驱动。在构造函数中根据配置连接redis服务器。

    aps.net-core给我们提供了强大的配置功能,使用强类型的Options,一般,我们实现一个继承自IOptions<TOptions>的类。定义一些字段用来表示主机,端口等常规redis配置选项。由于IOptions接口定义了一个Value属性,我们可以通过这个属性来获取配置类的实例。
    然后我们在redis客户端类中(也就是上面的ServiceStackRedisCache类),使用构造函数注入。这样就能获取到redis的配置了。
    然后我们在控制器的构造函数中注入redis客户端类实例:

    private readonly IServiceStackRedisCache _cache;
    public ValuesController(IServiceStackRedisCache cache)
    {
        _cache = cache;
    }

    如此,我们才能使用redis客户端去操作redis服务器。
    最后就是最重要的部分了。ASP.NET-CORE框架随处可见的都是依赖注入。上面所有的程序,都是一个接口对应着一个类。所谓的依赖注入,其实就是继承自接口的类的实例化过程,但是这个过程是解耦的!DI的作用主要就是用来解耦实例化的过程。
    ASP.NET-CORE框架依赖注入部分是在ConfigureService中使用的。
    从上面的过程中,我们看到有两个构造函数的注入过程,因此,我们需要实现两个DI,分别是配置类的DI和redis客户端类的DI。

    services.Configure(setupAction);
    
    services.Add(ServiceDescriptor.Singleton<IServiceStackRedisCache, ServiceStackRedisCache>());

    整个步骤就是:
    1.定义接口,用于继承IDistributedCache的接口。该接口主要封装了基本的redis操作。
    2.实现接口,实现redis的各个逻辑。
    3.基于IOptions<TOptions>接口实现redis的常规配置。
    4.在控制器的构造函数中注入。
    5.依赖注入以上接口的实例。

    完整demo下载:链接:https://pan.baidu.com/s/17w0c0y9_VF3TzvgilgazjQ 密码:4u5e

  • 相关阅读:
    从七牛云迁移图片到github
    Ajax 结构及使用
    JQuery 简单的文字超出部分隐藏下拉显示
    JQuery 动画及一些小知识点
    Jqurey DOM 操作详解
    Jquery DOM 操作列表
    文件上传以及JS链式结构
    JQuery选择器
    JQuery 基本知识
    LinQ to sql 各种数据库查询方法
  • 原文地址:https://www.cnblogs.com/zhiyong-ITNote/p/8985786.html
Copyright © 2011-2022 走看看