从0到1,为ASP.NET Core项目添加redis支持(全程使用copilot编码) ...

打印 上一主题 下一主题

主题 545|帖子 545|积分 1635

提示:文章写完后,目次可以自动生成,怎样生成可参考右边的帮助文档
  
  

前言

最近做需求需要用到redis,之前只在java用过,c#的使用还不清楚,故总结记录一下工作流。全程使用copilot进行代码编写

一、需求背景

需求是一个简朴的获取token的需求,token获取需要经过http调用第三方系统,故为了减少http调用,设置redis来缓存token数据。

二、扣问copilot工作流

1.简朴扣问

上来就先简朴问问,怎样导入redis:

可以看到,由于是刚开始发起提问,没有上下文,它给我整个了python的,我需要c#的,故继续提问。

这次是c#的方法了,但是更类似那种本身测试来玩玩的写法, 不符合我们的ASP.NET Core项目需求,故再次详细提问。



可以看到,这次的回答就比力详细了,从appsetting配置,到startup的注入,到现实代码里面的使用(他这里是直接在controller里面使用,我们一样平常照旧建个RedisHeloer工具类来统一使用,后面再详细扣问这方面)都有给出。至此,理论上是可以完备的测试并使用redis了,但是,我们还需相识更多细节才气应用到本身的代码里。
2.细节扣问

我们可以注意到,固然上一步中给出了大体使用步骤,但是还有一些地方的细节是含糊不清的,好比这个redis的ConnectionString,就写得比力不清不楚,一个localhost,显然不能满足需求

故就此细节再次进行提问:


这次的回答就比力详细了,从中我们可知redis链接串还可以指定端标语,指定暗码,指定命据库等属性,终极我们也是直接采用了它给出的完备配置。
至此,对应到我们的项目中,已经添加了如下代码:
首先是appsetting文件,界说了链接串:
  1.   "Redis": {
  2.     "ConnectionString": "localhost:6379,password=yourpassword,ssl=False,abortConnect=False,defaultDatabase=0"
  3.   }
复制代码
然后是startup文件,界说了redis链接的注入,以及我们redis工具类的注入:
  1.     public static void ConfigureServices(IServiceCollection services,
  2.         IConfigurationManager configuration)
  3.     {
  4.         // redis setting
  5.         var redisConnectionString = configuration.GetSection("Redis:ConnectionString").Value;
  6.         services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(redisConnectionString));
  7.         services.AddScoped<RedisHelper>();
  8.     }
复制代码
完成基础的配置跟注入后,就是详细的功能方法的提问,


现在我需要一个方法,可以做到redis有值的时间取值,无值的时间调用我传入的方法获取值,并set到redis去。可以看到,copilot给我返回了一个代码,但是注意,里面涉及了序列化与反序列化方法,并没有实现,我们可以继续就此追问。


这里它 给出了两种实现json序列化与反序列化的两种方式,System.Text.Json 和 Newtonsoft.Json ,我这里使用 Newtonsoft.Json 。
同时,我们设置rediskey跟value的时间,需要思量逾期时间,故继续扣问怎样设置逾期时间。


可以看到,我们可以用StringSet方法来设置逾期时间,它接收TimeSpan范例的参数。为了代码方便管理,像redis的逾期时间,还有前面提到的rediskey,一样平常都是界说好常量,直接使用,而TimeSpan范例,由于不能设置成常量,以是我们把常量界说为逾期时间的数值。
至此,对应到我们的项目中,又新添加了如下代码:
界说常量的静态类,界说了key跟逾期时间。逾期时间设置为3500s,是因为我们调用http接口获取的token逾期时间是3600s,这样能包管让时间全覆盖
  1.     public static class RedisConstants
  2.     {
  3.         public static class RedisKeys
  4.         {
  5.             public const string CRM_ADMIN_TOKEN_KEY = "crm_admin_token_key";
  6.         }
  7.         public static class RedisExpireTime
  8.         {
  9.             // 3500s
  10.             public const int CRM_ADMIN_TOKEN_EXPIRE_TIME = 3500;
  11.         }
  12.     }
复制代码
界说redis调用的RedisHelper工具类:
  1.     public class RedisHelper
  2.     {
  3.         private readonly IDatabase _database;
  4.         public RedisHelper(IConnectionMultiplexer connectionMultiplexer)
  5.         {
  6.             _database = connectionMultiplexer.GetDatabase();
  7.         }
  8.         public T GetOrSetValue<T>(string key, int expirtime, Func<T> valueFactory)
  9.         {
  10.             // 尝试从Redis获取值
  11.             var value = _database.StringGet(key);
  12.             if (value.HasValue)
  13.             {
  14.                 Console.WriteLine("Get value from Redis!");
  15.                 // 如果存在,反序列化并返回
  16.                 return Deserialize<T>(value);
  17.             }
  18.             else
  19.             {
  20.                 Console.WriteLine("redis not value , Get value from Factory!");
  21.                 // 如果不存在,调用valueFactory获取值
  22.                 var newValue = valueFactory();
  23.                 // 序列化并存储到Redis
  24.                 _database.StringSet(key, Serialize(newValue), TimeSpan.FromSeconds(expirtime));
  25.                 return newValue;
  26.             }
  27.         }
  28.         private byte[] Serialize<T>(T value)
  29.         {
  30.             // 实现序列化逻辑,根据实际情况选择合适的序列化方式
  31.             var jsonString = JsonConvert.SerializeObject(value);
  32.             return System.Text.Encoding.UTF8.GetBytes(jsonString);
  33.         }
  34.         private T Deserialize<T>(RedisValue value)
  35.         {
  36.             // 实现反序列化逻辑,根据实际情况选择合适的反序列化方式
  37.             var jsonString = System.Text.Encoding.UTF8.GetString(value);
  38.             return JsonConvert.DeserializeObject<T>(jsonString);
  39.         }
  40.     }
复制代码
3.代码定制化

至此,copilot已经给出一套完备的demo了,但是,还不敷。毕竟copilot无法直接读取整个项目标上下文,只能根据提问给出一些比力通用的办理方案,我们还要思量本身的项目本身,怎样让copilot给出的建议代码更好的融入我们的项目。还记得我之前提到的http调用的方法吗?该方法是一个异步的方法,通过http调用来获取token。
该获取token的方法署名如下
  1. public async Task<string> GetAdminTokenFromCRM(string authParam)
复制代码
而copilot建议的代码如下
  1. public T GetOrSetValue<T>(string key, int expirtime, Func<T> valueFactory)
复制代码
这个传入的方法并不是异步方法,且GetOrSetValue方法也不是异步的,故需要进行改造,一开始我按本身的想法来改,但是照旧比力缺少对异步编程这块的知识,报了几个错。于是把代码圈中扣问copilot


可以看到,copilot已经针对我错误的改造给出了建议。
同时也让我相识到Task的一些相关知识,在此概括总结下:
1.假如用Task界说了一个异步方法A,那么调用这个方法A的方法,以及所有的上层方法都要用 async Task 来界说
2.调用异步方法时,要在前面加 await 关键字
3.异步方法内部可以调同步方法,调用同步方法时无需加 await 关键字
至此完成了代码的定制化
终极,对应到我们的项目中,又新添加,或者更改了如下代码:
AlthHelper类,
  1.     public class CRMAuthHelper
  2.     {
  3.         private readonly CRMHttpHelper _cRMHttpHelper;
  4.         private readonly RedisHelper _redisHelper;
  5.         public CRMAuthHelper(CRMHttpHelper cRMHttpHelper,RedisHelper redisHelper)
  6.         {
  7.             _cRMHttpHelper = cRMHttpHelper;
  8.             _redisHelper = redisHelper;
  9.         }
  10.         public async Task<string> GetAdminiToken(string authParam)
  11.         {
  12.             string token = await GetFromRedis(authParam);
  13.             return token;
  14.         }
  15.         public async Task<string> GetFromRedis(string authParam)
  16.         {
  17.             string token = await _redisHelper.GetOrSetValue<string>(RedisConstants.RedisKeys.CRM_ADMIN_TOKEN_KEY,
  18.                 RedisConstants.RedisExpireTime.CRM_ADMIN_TOKEN_EXPIRE_TIME,
  19.                 () => _cRMHttpHelper.GetAdminTokenFromCRM(authParam));
  20.             return token;
  21.         }
  22.     }
复制代码
更改后的RedisHelper工具类
  1.     public class RedisHelper
  2.     {
  3.         private readonly IDatabase _database;
  4.         public RedisHelper(IConnectionMultiplexer connectionMultiplexer)
  5.         {
  6.             _database = connectionMultiplexer.GetDatabase();
  7.         }
  8.         public async Task<T> GetOrSetValue<T>(string key, int expirtime, Func<Task<T>> valueFactory)
  9.         {
  10.             // 尝试从Redis获取值
  11.             var value = _database.StringGet(key);
  12.             if (value.HasValue)
  13.             {
  14.                 Console.WriteLine("Get value from Redis!");
  15.                 // 如果存在,反序列化并返回
  16.                 return Deserialize<T>(value);
  17.             }
  18.             else
  19.             {
  20.                 Console.WriteLine("redis not value , Get value from Factory!");
  21.                 // 如果不存在,调用valueFactory获取值
  22.                 var newValue = await valueFactory();
  23.                 // 序列化并存储到Redis
  24.                 _database.StringSet(key, Serialize(newValue), TimeSpan.FromSeconds(expirtime));
  25.                 return newValue;
  26.             }
  27.         }
  28.         private byte[] Serialize<T>(T value)
  29.         {
  30.             // 实现序列化逻辑,根据实际情况选择合适的序列化方式
  31.             var jsonString = JsonConvert.SerializeObject(value);
  32.             return System.Text.Encoding.UTF8.GetBytes(jsonString);
  33.         }
  34.         private T Deserialize<T>(RedisValue value)
  35.         {
  36.             // 实现反序列化逻辑,根据实际情况选择合适的反序列化方式
  37.             var jsonString = System.Text.Encoding.UTF8.GetString(value);
  38.             return JsonConvert.DeserializeObject<T>(jsonString);
  39.         }
  40.     }
复制代码
下面是调用获取token时的局部代码,仅需调用AuthHelper即可
  1.             // get adminauth
  2.             string accesstoken = await _authHelper.GetAdminiToken(cRMSystemConfig.AuthParam);
复制代码
三、终极验证

下面验证一下,首先是初次调用时,确实走到了http调用获取token的方法

第二次再调用,则会直接使用redis里面的值


总结

以上就是本次copilot的使用工作流,在此总结一下:
1.对于自身的需求,可以先抛出简朴的提示词
2.再根据copilot的回答进一步引导提问并优化细节
3.针对终极的建议代码,再次进行定制化提问,以顺应已有项目
每日一遍,copilot真是太好用啦!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

火影

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表