由于是基于.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) == )
{
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 > )
{
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) == )
{
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 ;
}
} 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 = ; 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 = ; 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
}
}

在这里我们使用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

asp.net core 上使用redis探索(3)--redis示例demo的更多相关文章

  1. asp.net core上使用Redis探索(2)

    在<<asp.net core上使用Redis探索(1)>>中,我介绍了一个微软官方实现Microsoft.Extensions.Caching.Redis的类库,这次,我们使 ...

  2. 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射

    使用Code First建模自引用关系笔记   原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...

  3. asp.net core上使用Redis demo

    整体思路:(1.面向接口编程 2.Redis可视化操作IDE 3.Redis服务) [无私分享:ASP.NET CORE 项目实战(第十一章)]Asp.net Core 缓存 MemoryCache ...

  4. Asp.Net Core Web应用程序—探索

    前言 作为一个Windows系统下的开发者,我对于Core的使用机会几乎为0,但是考虑到微软的战略规划,我觉得,Core还是有先了解起来的必要. 因为,目前微软已经搞出了两个框架了,一个是Net标准( ...

  5. 在ASP.NET Core上实施每个租户策略的数据库

    在ASP.NET Core上实施每个租户策略的数据库 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: http://g ...

  6. Angular 2的HTML5 pushState在ASP.NET Core上的解决思路

    Angular 2的HTML5 pushState在ASP.NET Core上的解决思路 正如Angular 2在Routing & Navigation中所提及的那样,Angular 2是推 ...

  7. Asp.Net Core基于JWT认证的数据接口网关Demo

    近日,应一位朋友的邀请写了个Asp.Net Core基于JWT认证的数据接口网关Demo.朋友自己开了个公司,接到的一个升级项目,客户要求用Aps.Net Core做数据网关服务且基于JWT认证实现对 ...

  8. asp.net core系列 39 Razor 介绍与详细示例

    原文:asp.net core系列 39 Razor 介绍与详细示例 一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor ...

  9. asp.net core上使用redis探索(1)

    基于Ubuntu安装redis, 我找的一个很好的网站: https://www.digitalocean.com/community/tutorials/how-to-install-and-con ...

  10. 第十二节:Asp.Net Core 之分布式缓存(SQLServer和Redis)

    一. 整体说明 1. 说明 分布式缓存通常是指在多个应用程序服务器的架构下,作为他们共享的外部服务共享缓存,常用的有SQLServer.Redis.NCache.     特别说明一下:这里的分布式是 ...

随机推荐

  1. Scala-IDE构建Maven项目

    本教程演示如何使用Scala-IDE构建一个Scala Maven项目. 1. 下载Scala IDE 通过以下链接下载Scala IDE: http://scala-ide.org/download ...

  2. 图书管理系统(无中间件,用装饰器的)-----未基于FORM组件

    目的:实现图书的增删改查 models.py from django.db import models # Create your models here. class Book(models.Mod ...

  3. ActiveMQ消息的持久化策略

    持久化消息和非持久化消息的存储原理: 正常情况下,非持久化消息是存储在内存中的,持久化消息是存储在文件中的.能够存储的最大消息数据在${ActiveMQ_HOME}/conf/activemq.xml ...

  4. txt文档去重复内容

    @echo off for /f "delims=" %%i in ('type "%1"') do (if not defined %%i set %%i=A ...

  5. Tomcat配置域名/IP访问及其中遇到的问题注意事项

    1.先在tomcat下的conf下找到server.xml文件,用记事本打开后,首先对端口号进行修改,以前一直以为8080是默认的端口号,其实默认的端口号是80 <Connector port= ...

  6. wampserver本地配置域名映射

    本地开发时,一般是在浏览器输入 http://localhost/项目文件夹名 来测试网页文件,你有没有想过在本地在浏览器输入你自己设定的一个域名进入项目文件夹中去,本地配置多域名可以测试二级域名以及 ...

  7. Play框架--初学笔记

    目录结构 web_app 根目录 | sbt SBT Unix 批处理脚本用于启动sbt-launch.jar | sbt.bat SBT Windows 批处理脚本用于启动sbt-launch.ja ...

  8. error: each element of 'ext_modules' option must be an Extension instance or 2-tuple

    在编译cython扩展时出现. 解决办法: 必须先import setup再import extension,否则报错 from setuptools import setup from distut ...

  9. 【C++ Primer | 11】关联容器(一)

    在multimap或multiset中查找元素 第二种方法解释: #include <iostream> #include <utility> #include <ite ...

  10. Refs & DOM

    Refs 提供了一种访问在 render 方法中创建的 DOM 节点或 React 元素的方式. 在典型的 React 数据流中, 属性(props)是父组件与子代交互的唯一方式.要修改子组件,你需要 ...