经过前面章节的学习,可以说大家已经算Redis开发入门了。已经可以去到项目上磨砺了。

但是今天我还想和大家分享一章:封装自己的Redis C#库,然后打包成Nuget包。

首先要说明的是:不是要自己开发一个Redis客户端库,而是基于上篇文章中介绍的6大库,做一个简单封装,真的很简单的那种,就是包个壳子。

再来说说为什么要做这个事情。

01、原因

1.可测试

我希望代码是以服务的方式注入到程序中,而不是静态方法的方式去调用。使用依赖注入来提供服务使得程序可测试性增强,如果做单元测试,依赖注入的服务很容易通过mock来测试,而静态方法往往很难被模拟,测试起来很不灵活;

2.解耦

对于一个系统来说会使用到各种技术来达到某种能力,实现一个功能可能会有很多种方法,我们在意的是实现这个功能,而不是你用了什么方法。回到主题,我们需要的是使用Redis来实现业务功能,而具体用那个客户端库并不重要。

再举个例子比如今天我们选择了ServiceStack.Redis库接过遇到问题我们解决不了怎么办?难道业务不做了?不可能吧!而恰巧这个时候CSRedisCore库可以解决,你会怎么选?

这时候可能会想换的成本有多大?两种库方法名不统一,功能也不一样,如果系统中到处散落Redis方法调用,这可怎么换啊。

试想如果我们封装了一层,提供了一组接口,打包成Nuget包,这个时候大家用的就是这个Nuget包,而我们只需要把Nuget包里用ServiceStack.Redis实现的方法换成用CSRedisCore实现一下,大家直接更新一下Nuget包,可能一行代码都不用改就完成了替换。

因为我们依赖的是我们自己封装的接口,而不是具体Redis客户端库,因此可以解耦轻松替换。

3.扩展

Redis的原生功能可以理解为基础功能,表明Redis有这种能力。但是我们怎么使用,怎么更好的发挥它的价值,这就是我们自己能力的体现了。

大家相过想过没有,为什么有的库商业化做的特别好,特别简单容易上手。商业化好说明提供的服务好,也就是说明它能帮你做很多事情,它在原生功能上加了很多自己的创作。

项目做多了,我们自己也会遇到一些相似的功能,如果这个时候我们想把这些相似功能封装一下,要放哪里呢?怎么给别人用?如果我们遇到一个功能现有库都没有相应能力,需要我们基于原生自己开发实现又应该在哪做呢?

这些功能积累的多了总要有个地方放吧,而这时如果我们自己封装了一层,放哪的问题是不是一下子就解决了,说不定做着做着就成了一个产品了呢。

不知道到这里,大家有没有感觉思路一下子被打开了。可能我们没写几行代码,但是这个格局一下子就打开了,而这几行代码也可能产生意想不到的收获,可能是无限可能,也可能就是你实现自己Redis客户端库的开端。

当然这也是我自己对编码,对封装的个人拙见。说这么多也是希望可以给大家一些帮助。

02、实现

下面闲话少说进入正题,如果来封装呢?

我们先梳理一下大致思路:

1.我们需要一个接口,里面包含:原库原生能力Client、其他我们自定义功能。

2.一个入口,别人要用,总要有个入口吧。

其实要求就这么简单。

下面我们就以封装CSRedisClient为例,首先定义IRedisService接口,里面包含Client字段以及两个演示的自定义方法

using CSRedis;
namespace Redis.RedisExtension
{
public interface IRedisService
{
/// <summary>
/// RedisClient
/// </summary>
/// <returns></returns>
CSRedisClient Client { get; }
#region 自定义方法
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
T Get<T>(string key);
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
Task<T> GetAsync<T>(string key);
#endregion
}
}

然后需要实现IRedisService,同时以CSRedisClient为构造函数入参,具体代码如下:

using CSRedis;
namespace Redis.RedisExtension
{
public class RedisService : IRedisService
{
/// <summary>
/// 构造函数
/// </summary>
/// <param name="redisClient"></param>
public RedisService(CSRedisClient redisClient)
{
Client = redisClient;
}
/// <summary>
/// CSRedis
/// </summary>
/// <returns></returns>
public CSRedisClient Client { get; }
#region 自定义方法
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <returns></returns>
public T Get<T>(string key)
{
return Client.Get<T>(key);
}
/// <summary>
/// 获取指定 key 的值
/// </summary>
/// <returns></returns>
public Task<T> GetAsync<T>(string key)
{
return Client.GetAsync<T>(key);
}
#endregion
}
}

到这里第一个问题就解决了,对于第二个问题我们,我们可以对IServiceCollection进行扩展添加启动扩展方法AddRedisClientSetup,具体代码如下:

using CSRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Redis.RedisExtension
{
public static class RedisSetupExtensions
{
/// <summary>
/// Redis客户端启动项
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddRedisClientSetup(this IServiceCollection services)
{
services.AddSingleton<CSRedisClient>(serviceProvider =>
{
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
var setting = configuration["RedisConnectionString"];
return new CSRedisClient(setting);
});
services.AddSingleton<IRedisService, RedisService>();
return services;
}
/// <summary>
/// Redis客户端启动项
/// </summary>
/// <param name="services"></param>
/// <param name="connectionString"></param>
/// <returns></returns>
public static IServiceCollection AddRedisClientSetup(this IServiceCollection services, string connectionString)
{
services.AddSingleton<CSRedisClient>(serviceProvider =>
{
return new CSRedisClient(connectionString);
});
services.AddSingleton<IRedisService, RedisService>();
return services;
}
}
}

为什么要提供两个重载方法,因为如果用户基于我们的约定,在配置文件中以"RedisConnectionString"命名Redis连接字符串,用户直接调用AddRedisClientSetup()方法即可完成Redis启动,但是可能因为各种原因用户没法遵守约定,因此我们也要提供一个用户可以指定Redis连接字符串方法的入口。

下面我们就用基于约定的方式,在配置文件中加入以下配置:

{
"RedisConnectionString": "127.0.0.1:6379"
}

然后使用Client.Set方法设置key1,再用自定义方法Get方法读取,代码如下:

public static void Run()
{
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(configuration);
services.AddRedisClientSetup();
var redisService = services.BuildServiceProvider().GetService<IRedisService>();
var setResult = redisService.Client.Set("key1", "value1");
Console.WriteLine($"redisService.Client.Set(\"key1\",\"value1\")执行结果:{setResult}");
var value = redisService.Get<string>("key1");
Console.WriteLine($"redisService.Get<string>(\"key1\")执行结果:{value}");
redisService.Client.Del("key1");
}

执行结果如下:

是不是很简单,然后我们只需要把上面三个文件IRedisService、RedisService、RedisSetupExtensions放到单独的类库中,然后打包发布成Nuget包,就可以给大家一起用啦,今天我这边就不发布Nuget包了,后面会有相关的计划,到时候再细聊。

:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

Redis入门 - C#|.NET Core封装Nuget包的更多相关文章

  1. asp.net core 三 Nuget包管理

        参考连接:http://www.cnblogs.com/netcore2/p/7412891.html     这里的说明,基本就是学习了别人的文章,自己做了个备份     asp.net c ...

  2. 解决 .net core 中 nuget 包版本冲突问题

    今天在一个 asp.net core 项目中遇到了 nuget 包版本冲突的问题,错误信息如下: Version conflict detected for Microsoft.AspNet.WebA ...

  3. .Net core 还原Nuget包失败的解决方法

    今天是2018最后一天了,真是神奇的一年啊,写个博客压压惊,来年继续加油吧..... 正文: 当我们打开.net core 项目时候,发现输出提示nuget包还原失败,这个时候首先要考虑.Net Co ...

  4. 解决 .net core 中 nuget 包版本冲突问题[转载]

    今天在一个 asp.net core 项目中遇到了 nuget 包版本冲突的问题,错误信息如下: Version conflict detected for Microsoft.AspNet.WebA ...

  5. 【NET Core】Nuget包发布流程

    1.新建一个.NET Core类库 2.新增一个方法,并编译项目 3.下载Nuget.exe,与刚才新建的类库放在同一目录下 下载地址:https://www.nuget.org/downloads ...

  6. NetCore入门篇:(三)Net Core项目Nuget及Bower包管理

    一.创建项目 1.如何创建项目,参照上一篇文章 二.程序包介绍 1.Net Core的程序包分前后端两种,后端用nuget,前端用bower. 2.与Net 不同,Net Core引用nuget包时, ...

  7. .NET Core 学习笔记2——管理nuget包

    .NET Core 基于Nuget包.它是一个.nupkg后缀的zip文件. 工具 dotnet 工具 vs2017 的程序包管理控台 这两个工具都可以用命令行来下载安装,更新,上传包(上传要先在网站 ...

  8. .NET Core 环境下使用命令行移除某个 nuget 包的具体方法

    .NET Core 使用Nuget包一般是先写入csproj文件,然后下载保存在\bin\Debug\netcoreapp2.0\publish\下,所以可以采用如下方案进行删除操作(其中netcor ...

  9. 001从零开始入门Entity Framework Core——基础知识

    Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台版的常用 Entity Framework 数据访问技术. 一.什么是 Entity Framework Core ...

  10. 基于 Vue.js 之 iView UI 框架非工程化实践记要 使用 Newtonsoft.Json 操作 JSON 字符串 基于.net core实现项目自动编译、并生成nuget包 webpack + vue 在dev和production模式下的小小区别 这样入门asp.net core 之 静态文件 这样入门asp.net core,如何

    基于 Vue.js 之 iView UI 框架非工程化实践记要   像我们平日里做惯了 Java 或者 .NET 这种后端程序员,对于前端的认识还常常停留在 jQuery 时代,包括其插件在需要时就引 ...

随机推荐

  1. Python潮流周刊的优惠券和精美电子书(EPUB、PDF、Markdown)

    Python潮流周刊从 2023.05.13 连载至今,本周即将发布第 60 期,这意味着我们又要达成一个小小的里程碑啦! 每周坚持做分享,周复一周,这对自己的精力和意志是一项不小的挑战.于是,为了让 ...

  2. Happus:给准备离职成为独立开发者的你 5 点建议

    名字:Happus 开发者 / 团队:Regina Dan 平台:iOS, visionOS 请简要介绍下这款产品 Happus 是你追寻幸福健康关系.甚至提高婚姻生活品质的贴心助手.无论是关系维系. ...

  3. 洛谷[NOIP2015 普及组] 金币

    [NOIP2015 普及组] 金币 题目背景 NOIP2015 普及组 T1 题目描述 国王将金币作为工资,发放给忠诚的骑士.第一天,骑士收到一枚金币:之后两天(第二天和第三天),每天收到两枚金币:之 ...

  4. gitbook 入门教程之比较代码块差异 diff 插件

    在 markdown 文档中显示代码之间的差异的 Gitbook 插件 English | 中文 主页 Github : https://snowdreams1006.github.io/gitboo ...

  5. JDK安装教程(Windows)

    Windows 端: 1. 安装 首先进入官网:https://www.oracle.com/java/technologies/javase-downloads.html 因为我已经安装了 JDK8 ...

  6. k8s 环境搭建(2)

    安装docker组件 配置本地源或者自带的网络源2选1 1.切换镜像源 wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce ...

  7. 【Mybatis】06 Session获取 & 配置参数总结

    会话获取 SqlSessionFactory 最佳的获取方式就是使用Mybatis提供的资源类加载配置文件 调用会话工厂建造者实例的建造方法注入读取流 要注意的是建造者生成了了实例就可以不需要了 这里 ...

  8. 使用 Alba 对 AspnetCore项目进行测试

    前言 在AspnetCore生态系统中,我们测试项目一般使用Microsoft.AspNetCore.TestHost的TestServer 到.NET6后提供的Microsoft.AspNetCor ...

  9. 国产操作系统 deepin —— UOS 系统下使用蓝牙音箱或蓝牙耳机不能正常工作

    近日搞来了一个国产CPU的电脑,自带系统为UOS,具体可见: https://www.cnblogs.com/devilmaycry812839668/p/14828130.html 忽然发现这个系统 ...

  10. vscode配置远程项目开发

    0. vscode中安装remote development插件 (略) 1. 客户端进行配置 按键:ctrl+shift+p 在输入框中输入: Preferences: Open User Sett ...