反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

时间:2023-12-12 12:35:32

反射实现Model修改前后的内容对比

在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责。

首先我们要创建一个User类

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
 1     public class User
 2     {
 3         private string name;
 4         public string Name
 5         {
 6             get { return name; }
 7             set { name = value; }
 8         }
 9         private string age;
10         public string Age
11         {
12             get { return age; }
13             set { age = value; }
14         }
15         private string sex;
16         public string Sex
17         {
18             get { return sex; }
19             set { sex = value; }
20         }
21     }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

然后在Main函数中声明并初始化一个User对象

1             User userA = new User()
2             {
3                 Name = "李四",
4                 Age = "25",
5                 Sex = "男",
6             };

因为要对比对象编辑前后的内容,所以需要备份一下这个UserA,我们来个深拷贝

1 User userB = DeepCopyByXml<User>(userA);
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
 1         /// <summary>
 2         /// 深拷贝
 3         /// </summary>
 4         /// <typeparam name="T"></typeparam>
 5         /// <param name="obj"></param>
 6         /// <returns></returns>
 7         public static T DeepCopyByXml<T>(T obj) where T : class
 8         {
 9             object retval;
10             using (MemoryStream ms = new MemoryStream())
11             {
12                 XmlSerializer xml = new XmlSerializer(typeof(T));
13                 xml.Serialize(ms, obj);
14                 ms.Seek(0, SeekOrigin.Begin);
15                 retval = xml.Deserialize(ms);
16                 ms.Close();
17             }
18             return (T)retval;
19         }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

接下来的工作是修改UserA的属性,然后和UserB对比,利用反射来实现该功能

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
        /// <summary>
        /// Model对比
        /// </summary>
        /// <typeparam Name="T"></typeparam>
        /// <param Name="oldModel"></param>
        /// <param Name="newModel"></param>
        private static void CompareModel<T>(T oldModel, T newModel) where T : class
        {
            string changeStr = string.Empty;
            PropertyInfo[] properties = oldModel.GetType().GetProperties();
            Console.WriteLine("--------用户信息修改汇总--------");
            foreach (System.Reflection.PropertyInfo item in properties)
            {string name = item.Name;
                object oldValue = item.GetValue(oldModel);
                object newValue = item.GetValue(newModel);
                if (!oldValue.Equals(newValue))
                {
                    Console.WriteLine(name + " :由[" + oldValue + "] 改为 [" + newValue + "]");
                }
            }
        }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

从运行结果来看我们已经获取到了修改的内容,美中不足的是“Name”和“Age”,如何以中文显示属性名,接下来将利用C#的特性来实现

新建一个自定义的特性类TableAttribute

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
    /*
    参数 validon 规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
    参数 allowmultiple(可选的)为该特性的 AllowMultiple 属性(property)提供一个布尔值。如果为 true,则该特性是多用的。默认值是 false(单用的)。
    参数 inherited(可选的)为该特性的 Inherited 属性(property)提供一个布尔值。如果为 true,则该特性可被派生类继承。默认值是 false(不被继承)。
     */
    [AttributeUsage(AttributeTargets.Class |
    AttributeTargets.Field |
    AttributeTargets.Property,
          AllowMultiple = false,
          Inherited = false)]
    public class TableAttribute : System.Attribute
    {
        private string fieldName;
        private string tableName;
        /// <summary>
        /// 表名
        /// </summary>
        public string TableName
        {
            get { return tableName; }
            set { tableName = value; }
        }
        /// <summary>
        /// 字段名
        /// </summary>
        public string FieldName
        {
            get { return fieldName; }
            set { fieldName = value; }
        }
    }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

接着修改User类,加上自定义的特性TableAttribute

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
    /// <summary>
    /// 用户信息实体类
    /// </summary>
    [TableAttribute(TableName = "用户信息")]
    public class User
    {
        private string name;
        [TableAttribute(FieldName = "姓名")]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private string age;
        [TableAttribute(FieldName = "年龄")]
        public string Age
        {
            get { return age; }
            set { age = value; }
        }
        private string sex;
        [TableAttribute(FieldName = "性别")]
        public string Sex
        {
            get { return sex; }
            set { sex = value; }
        }
    }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

最后修改一下CompareModel这个方法

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
 1         /// <summary>
 2         /// Model对比
 3         /// </summary>
 4         /// <typeparam Name="T"></typeparam>
 5         /// <param Name="oldModel"></param>
 6         /// <param Name="newModel"></param>
 7         private static void CompareModel<T>(T oldModel, T newModel) where T : class
 8         {
 9             string changeStr = string.Empty;
10             PropertyInfo[] properties = oldModel.GetType().GetProperties();
11             Console.WriteLine("--------用户信息修改汇总--------");
12             foreach (System.Reflection.PropertyInfo item in properties)
13             {
14                 TableAttribute tableAttribute = item.GetCustomAttribute<TableAttribute>();
15                 string name = item.Name;
16                 if (tableAttribute != null)
17                     name = tableAttribute.FieldName;
18                 object oldValue = item.GetValue(oldModel);
19                 object newValue = item.GetValue(newModel);
20                 if (!oldValue.Equals(newValue))
21                 {
22                     Console.WriteLine(name + " :由[" + oldValue + "] 改为 [" + newValue + "]");
23                 }
24             }
25         }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

我们看一下运行结果

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

完整demo下载:https://files.cnblogs.com/files/LikeHeart/ExampleReflection.zip

(完)

【API调用】腾讯云短信

在之前介绍的火车票查询工具中,利用邮件和短信将查询结果推送给用户。免费短信的条数只有5条,用完之后只能单独使用邮件提醒。

最近发现腾讯云的福利,简单的介绍一下用法。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

腾讯云-》产品-》通信服务-》短信-》开通服务-》添加应用-》创建签名和模板-》等待审核通过-》按照Demo测试

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

在整个流程中,最耗时的就是创建签名和模板,对个人来说只能选择app、公众号或小程序的方式进行申请,多亏之前折腾过一点小程序,从而闯关成功。

接下来查看官方Demo https://github.com/qcloudsms/qcloudsms/tree/master/demo/csharp

整理后的测试Demo

调用代码:

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
 1 using QcloudSms;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 using System.Threading.Tasks;
 7
 8 namespace ConsoleTest
 9 {
10     class SmsSDKDemo
11     {
12         /// <summary>
13         /// appId
14         /// </summary>
15         private static int appId = 140xxxxx;
16         /// <summary>
17         /// appKey
18         /// </summary>
19         private static string appKey = "xxxxxxxxxxxxxxx";
20         /// <summary>
21         /// 接收手机号
22         /// </summary>
23         private static string phoneNumber = "xxxxxxxx";
24         /// <summary>
25         /// 短信模板ID
26         /// </summary>
27         private static int tmplateId = xxxxxxx;
28
29         static void Main(string[] args)
30         {
31             try
32             {
33                 SmsSingleSenderResult singleResult;
34                 SmsSingleSender singleSender = new SmsSingleSender(appId, appKey);
35
36                 singleResult = singleSender.Send(SmsType.普通短信, phoneNumber, "");
37                 Console.WriteLine(singleResult);
38
39                 List<string> templParams = new List<string>();
40                 templParams.Add("G2619");
41                 templParams.Add("二等座:23 无座:128");
42                 singleResult = singleSender.SendWithParam(phoneNumber, tmplateId, templParams);
43                 Console.WriteLine(singleResult);
44             }
45             catch (Exception e)
46             {
47                 Console.WriteLine(e);
48             }
49             Console.Read();
50         }
51     }
52 }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
  1 namespace QcloudSms
  2 {
  3     #region 短信类型枚举
  4     /// <summary>
  5     /// 短信类型枚举
  6     /// </summary>
  7     public enum SmsType
  8     {
  9         普通短信 = 0,
 10         营销短信 = 1
 11     }
 12     #endregion
 13
 14     #region 单发
 15     /// <summary>
 16     /// 单发
 17     /// </summary>
 18     class SmsSingleSender
 19     {
 20         #region 变量
 21         /// <summary>
 22         /// appId
 23         /// </summary>
 24         private int appId;
 25         /// <summary>
 26         /// appkey
 27         /// </summary>
 28         private string appkey;
 29         /// <summary>
 30         /// url
 31         /// </summary>
 32         private string url = "https://yun.tim.qq.com/v5/tlssmssvr/sendsms";
 33         /// <summary>
 34         /// util
 35         /// </summary>
 36         private SmsSenderUtil util = new SmsSenderUtil();
 37         #endregion
 38
 39         #region 构造
 40         /// <summary>
 41         /// 构造函数
 42         /// </summary>
 43         /// <param name="sdkappid"></param>
 44         /// <param name="appkey"></param>
 45         public SmsSingleSender(int sdkappid, string appkey)
 46         {
 47             this.appId = sdkappid;
 48             this.appkey = appkey;
 49         }
 50         #endregion
 51
 52         #region 普通单发短信接口
 53         /// <summary>
 54         /// 普通单发短信接口,明确指定内容,如果有多个签名,请在内容中以【】的方式添加到信息内容中,否则系统将使用默认签名
 55         /// </summary>
 56         /// <param name="type">短信类型,0 为普通短信,1 营销短信</param>
 57         /// <param name="phoneNumber">不带国家码的手机号</param>
 58         /// <param name="msg">信息内容,必须与申请的模板格式一致,否则将返回错误</param>
 59         /// <param name="extend">短信码号扩展号,格式为纯数字串,其他格式无效。默认没有开通</param>
 60         /// <param name="ext">服务端原样返回的参数,可填空</param>
 61         /// <returns>SmsSingleSenderResult</returns>
 62         public SmsSingleSenderResult Send(SmsType type, string phoneNumber, string msg, string extend = "", string ext = "")
 63         {
 64             long random = util.GetRandom();
 65             long curTime = util.GetCurTime();
 66
 67             // 按照协议组织 post 请求包体
 68             JObject tel = new JObject();
 69             tel.Add("nationcode", SmsSenderUtil.nationCode);
 70             tel.Add("mobile", phoneNumber);
 71             JObject data = new JObject();
 72             data.Add("tel", tel);
 73             data.Add("msg", msg);
 74             data.Add("type", (int)type);
 75             data.Add("sig", util.StrToHash(string.Format("appkey={0}&random={1}&time={2}&mobile={3}", appkey, random, curTime, phoneNumber)));
 76             data.Add("time", curTime);
 77             data.Add("extend", extend);
 78             data.Add("ext", ext);
 79
 80             string wholeUrl = url + "?sdkappid=" + appId + "&random=" + random;
 81             HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
 82             byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
 83             request.ContentLength = requestData.Length;
 84             Stream requestStream = request.GetRequestStream();
 85             requestStream.Write(requestData, 0, requestData.Length);
 86             requestStream.Close();
 87
 88             // 接收返回包
 89             HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 90             Stream responseStream = response.GetResponseStream();
 91             StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
 92             string responseStr = streamReader.ReadToEnd();
 93             streamReader.Close();
 94             responseStream.Close();
 95             SmsSingleSenderResult result;
 96             if (HttpStatusCode.OK == response.StatusCode)
 97             {
 98                 result = util.ResponseStrToSingleSenderResult(responseStr);
 99             }
100             else
101             {
102                 result = new SmsSingleSenderResult();
103                 result.result = -1;
104                 result.errmsg = "http error " + response.StatusCode + " " + responseStr;
105             }
106             return result;
107         }
108         #endregion
109
110         #region 指定模板单发
111         /// <summary>
112         /// 指定模板单发
113         /// </summary>
114         /// <param name="phoneNumber">不带国家码的手机号</param>
115         /// <param name="templId">模板 id</param>
116         /// <param name="templParams">模板参数列表,如模板 {1}...{2}...{3},那么需要带三个参数</param>
117         /// <param name="sign">短信签名,如果使用默认签名,该字段可缺省</param>
118         /// <param name="extend">扩展码,可填空</param>
119         /// <param name="ext">服务端原样返回的参数,可填空</param>
120         /// <returns>SmsSingleSenderResult</returns>
121         public SmsSingleSenderResult SendWithParam(string phoneNumber, int templId, List<string> templParams, string sign = "", string extend = "", string ext = "")
122         {
123             long random = util.GetRandom();
124             long curTime = util.GetCurTime();
125
126             // 按照协议组织 post 请求包体
127             JObject tel = new JObject();
128             tel.Add("nationcode", SmsSenderUtil.nationCode);
129             tel.Add("mobile", phoneNumber);
130             JObject data = new JObject();
131             data.Add("tel", tel);
132             data.Add("sig", util.CalculateSigForTempl(appkey, random, curTime, phoneNumber));
133             data.Add("tpl_id", templId);
134             data.Add("params", util.SmsParamsToJSONArray(templParams));
135             data.Add("sign", sign);
136             data.Add("time", curTime);
137             data.Add("extend", extend);
138             data.Add("ext", ext);
139
140             string wholeUrl = url + "?sdkappid=" + appId + "&random=" + random;
141             HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
142             byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
143             request.ContentLength = requestData.Length;
144             Stream requestStream = request.GetRequestStream();
145             requestStream.Write(requestData, 0, requestData.Length);
146             requestStream.Close();
147
148             // 接收返回包
149             HttpWebResponse response = (HttpWebResponse)request.GetResponse();
150             Stream responseStream = response.GetResponseStream();
151             StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
152             string responseStr = streamReader.ReadToEnd();
153             streamReader.Close();
154             responseStream.Close();
155             SmsSingleSenderResult result;
156             if (HttpStatusCode.OK == response.StatusCode)
157             {
158                 result = util.ResponseStrToSingleSenderResult(responseStr);
159             }
160             else
161             {
162                 result = new SmsSingleSenderResult();
163                 result.result = -1;
164                 result.errmsg = "http error " + response.StatusCode + " " + responseStr;
165             }
166             return result;
167         }
168         #endregion
169     }
170     #endregion
171
172     #region 单发结果
173     /// <summary>
174     /// 单发结果
175     /// </summary>
176     class SmsSingleSenderResult
177     {
178         /// <summary>
179         /// 错误码,0 表示成功(计费依据),非 0 表示失败
180         /// </summary>
181         public int result { set; get; }
182         /// <summary>
183         /// 错误消息,result 非 0 时的具体错误信息
184         /// </summary>
185         public string errmsg { set; get; }
186         /// <summary>
187         /// 用户的 session 内容,腾讯 server 回包中会原样返回
188         /// </summary>
189         public string ext { set; get; }
190         /// <summary>
191         /// 本次发送标识 id,标识一次短信下发记录
192         /// </summary>
193         public string sid { set; get; }
194         /// <summary>
195         /// 短信计费的条数
196         /// </summary>
197         public int fee { set; get; }
198         /// <summary>
199         /// ToString()
200         /// </summary>
201         /// <returns></returns>
202         public override string ToString()
203         {
204             return string.Format("SmsSingleSenderResult\nresult {0}\nerrMsg {1}\next {2}\nsid {3}\nfee {4}", result, errmsg, ext, sid, fee);
205         }
206     }
207     #endregion
208
209     #region 群发
210     /// <summary>
211     /// 群发
212     /// </summary>
213     class SmsMultiSender
214     {
215         #region 变量
216         /// <summary>
217         /// appId
218         /// </summary>
219         private int appId;
220         /// <summary>
221         /// appkey
222         /// </summary>
223         private string appkey;
224         /// <summary>
225         /// url
226         /// </summary>
227         private string url = "https://yun.tim.qq.com/v5/tlssmssvr/sendmultisms2";
228         /// <summary>
229         /// util
230         /// </summary>
231         private SmsSenderUtil util = new SmsSenderUtil();
232         #endregion
233
234         #region 构造
235         /// <summary>
236         /// 构造
237         /// </summary>
238         /// <param name="sdkappid"></param>
239         /// <param name="appkey"></param>
240         public SmsMultiSender(int sdkappid, string appkey)
241         {
242             this.appId = sdkappid;
243             this.appkey = appkey;
244         }
245         #endregion
246
247         #region 普通群发短信接口
248         /// <summary>
249         /// 普通群发短信接口,明确指定内容,如果有多个签名,请在内容中以【】的方式添加到信息内容中,否则系统将使用默认签名
250         ///【注意】 海外短信无群发功能
251         /// </summary>
252         /// <param name="type">短信类型,0 为普通短信,1 营销短信</param>
253         /// <param name="nationCode"></param>
254         /// <param name="phoneNumbers">不带国家码的手机号列表</param>
255         /// <param name="msg">信息内容,必须与申请的模板格式一致,否则将返回错误</param>
256         /// <param name="extend">扩展码,可填空</param>
257         /// <param name="ext">服务端原样返回的参数,可填空</param>
258         /// <returns>SmsMultiSenderResult</returns>
259         public SmsMultiSenderResult Send(SmsType type, List<string> phoneNumbers, string msg, string extend = "", string ext = "")
260         {
261             long random = util.GetRandom();
262             long curTime = util.GetCurTime();
263
264             // 按照协议组织 post 请求包体
265             JObject data = new JObject();
266             data.Add("tel", util.PhoneNumbersToJSONArray(SmsSenderUtil.nationCode, phoneNumbers));
267             data.Add("type", (int)type);
268             data.Add("msg", msg);
269             data.Add("sig", util.CalculateSig(appkey, random, curTime, phoneNumbers));
270             data.Add("time", curTime);
271             data.Add("extend", extend);
272             data.Add("ext", ext);
273
274             string wholeUrl = url + "?sdkappid=" + appId + "&random=" + random;
275             HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
276             byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
277             request.ContentLength = requestData.Length;
278             Stream requestStream = request.GetRequestStream();
279             requestStream.Write(requestData, 0, requestData.Length);
280             requestStream.Close();
281
282             // 接收返回包
283             HttpWebResponse response = (HttpWebResponse)request.GetResponse();
284             Stream responseStream = response.GetResponseStream();
285             StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
286             string responseStr = streamReader.ReadToEnd();
287             streamReader.Close();
288             responseStream.Close();
289             SmsMultiSenderResult result;
290             if (HttpStatusCode.OK == response.StatusCode)
291             {
292                 result = util.ResponseStrToMultiSenderResult(responseStr);
293             }
294             else
295             {
296                 result = new SmsMultiSenderResult();
297                 result.result = -1;
298                 result.errmsg = "http error " + response.StatusCode + " " + responseStr;
299             }
300             return result;
301         }
302         #endregion
303
304         #region 指定模板群发
305         /// <summary>
306         /// 指定模板群发
307         /// 【注意】海外短信无群发功能
308         /// </summary>
309         /// <param name="phoneNumbers">不带国家码的手机号列表</param>
310         /// <param name="templId"> 模板 id</param>
311         /// <param name="templParams">模板参数列表</param>
312         /// <param name="sign"> 签名,如果填空,系统会使用默认签名</param>
313         /// <param name="extend">扩展码,可以填空</param>
314         /// <param name="ext">服务端原样返回的参数,可以填空</param>
315         /// <returns> SmsMultiSenderResult</returns>
316         public SmsMultiSenderResult SendWithParam(List<string> phoneNumbers, int templId, List<string> templParams, string sign = "", string extend = "", string ext = "")
317         {
318             long random = util.GetRandom();
319             long curTime = util.GetCurTime();
320
321             // 按照协议组织 post 请求包体
322             JObject data = new JObject();
323             data.Add("tel", util.PhoneNumbersToJSONArray(SmsSenderUtil.nationCode, phoneNumbers));
324             data.Add("sig", util.CalculateSigForTempl(appkey, random, curTime, phoneNumbers));
325             data.Add("tpl_id", templId);
326             data.Add("params", util.SmsParamsToJSONArray(templParams));
327             data.Add("sign", sign);
328             data.Add("time", curTime);
329             data.Add("extend", extend);
330             data.Add("ext", ext);
331
332             string wholeUrl = url + "?sdkappid=" + appId + "&random=" + random;
333             HttpWebRequest request = util.GetPostHttpConn(wholeUrl);
334             byte[] requestData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(data));
335             request.ContentLength = requestData.Length;
336             Stream requestStream = request.GetRequestStream();
337             requestStream.Write(requestData, 0, requestData.Length);
338             requestStream.Close();
339
340             // 接收返回包
341             HttpWebResponse response = (HttpWebResponse)request.GetResponse();
342             Stream responseStream = response.GetResponseStream();
343             StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
344             string responseStr = streamReader.ReadToEnd();
345             streamReader.Close();
346             responseStream.Close();
347             SmsMultiSenderResult result;
348             if (HttpStatusCode.OK == response.StatusCode)
349             {
350                 result = util.ResponseStrToMultiSenderResult(responseStr);
351             }
352             else
353             {
354                 result = new SmsMultiSenderResult();
355                 result.result = -1;
356                 result.errmsg = "http error " + response.StatusCode + " " + responseStr;
357             }
358             return result;
359         }
360         #endregion
361     }
362     #endregion
363
364     #region 群发结果
365     /// <summary>
366     /// 群发结果
367     /// </summary>
368     class SmsMultiSenderResult
369     {
370         public class Detail
371         {
372             /// <summary>
373             /// 错误码,0 表示成功(计费依据),非 0 表示失败
374             /// </summary>
375             public int result { get; set; }
376             /// <summary>
377             /// 错误消息,result 非 0 时的具体错误信息
378             /// </summary>
379             public string errmsg { get; set; }
380             /// <summary>
381             /// 手机号码
382             /// </summary>
383             public string mobile { get; set; }
384             /// <summary>
385             /// 国家码
386             /// </summary>
387             public string nationcode { get; set; }
388             /// <summary>
389             /// 本次发送标识 id,标识一次短信下发记录
390             /// </summary>
391             public string sid { get; set; }
392             /// <summary>
393             /// 短信计费的条数
394             /// </summary>
395             public int fee { get; set; }
396             /// <summary>
397             /// ToString()
398             /// </summary>
399             /// <returns></returns>
400             public override string ToString()
401             {
402                 return string.Format(
403                         "\tDetail result {0} errmsg {1} mobile {2} nationcode {3} sid {4} fee {5}",
404                         result, errmsg, mobile, nationcode, sid, fee);
405             }
406         }
407
408         public int result;
409         public string errmsg = "";
410         public string ext = "";
411         public IList<Detail> detail;
412
413         public override string ToString()
414         {
415             if (null != detail)
416             {
417                 return String.Format(
418                         "SmsMultiSenderResult\nresult {0}\nerrmsg {1}\next {2}\ndetail:\n{3}",
419                         result, errmsg, ext, String.Join("\n", detail));
420             }
421             else
422             {
423                 return String.Format(
424                      "SmsMultiSenderResult\nresult {0}\nerrmsg {1}\next {2}\n",
425                      result, errmsg, ext);
426             }
427         }
428     }
429     #endregion
430
431     #region 公共类
432     /// <summary>
433     /// 公共类
434     /// </summary>
435     class SmsSenderUtil
436     {
437         /// <summary>
438         /// 国家码
439         /// </summary>
440         public static string nationCode = "86";
441         /// <summary>
442         /// 随机数生成器
443         /// </summary>
444         private Random random = new Random();
445
446         #region GetPostHttpConn
447         /// <summary>
448         /// GetPostHttpConn
449         /// </summary>
450         /// <param name="url"></param>
451         /// <returns></returns>
452         public HttpWebRequest GetPostHttpConn(string url)
453         {
454             HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
455             request.Method = "POST";
456             request.ContentType = "application/x-www-form-urlencoded";
457             return request;
458         }
459         #endregion
460
461         #region 生成随机数
462         /// <summary>
463         /// 生成随机数
464         /// </summary>
465         /// <returns></returns>
466         public long GetRandom()
467         {
468             return random.Next(999999) % 900000 + 100000;
469         }
470         #endregion
471
472         #region 获取请求发起时间
473         /// <summary>
474         /// 获取请求发起时间,
475         /// unix 时间戳(单位:秒),如果和系统时间相差超过 10 分钟则会返回失败
476         /// </summary>
477         /// <returns></returns>
478         public long GetCurTime()
479         {
480             Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
481             return unixTimestamp;
482         }
483         #endregion
484
485         #region 字符串转SHA256
486         /// <summary>
487         /// 字符串转SHA256
488         /// </summary>
489         /// <param name="str"></param>
490         /// <returns></returns>
491         public string StrToHash(string str)
492         {
493             SHA256 sha256 = SHA256Managed.Create();
494             byte[] resultByteArray = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(str));
495             return ByteArrayToHex(resultByteArray);
496         }
497
498         /// <summary>
499         /// 将二进制的数值转换为 16 进制字符串,如 "abc" => "616263"
500         /// </summary>
501         /// <param name="byteArray"></param>
502         /// <returns></returns>
503         private static string ByteArrayToHex(byte[] byteArray)
504         {
505             string returnStr = "";
506             if (byteArray != null)
507             {
508                 for (int i = 0; i < byteArray.Length; i++)
509                 {
510                     returnStr += byteArray[i].ToString("x2");
511                 }
512             }
513             return returnStr;
514         }
515         #endregion
516
517         #region 将单发回包解析成结果对象
518         /// <summary>
519         /// 将单发回包解析成结果对象
520         /// </summary>
521         /// <param name="str"></param>
522         /// <returns></returns>
523         public SmsSingleSenderResult ResponseStrToSingleSenderResult(string str)
524         {
525             SmsSingleSenderResult result = JsonConvert.DeserializeObject<SmsSingleSenderResult>(str);
526             return result;
527         }
528         #endregion
529
530         #region 将群发回包解析成结果对象
531         /// <summary>
532         /// 将群发回包解析成结果对象
533         /// </summary>
534         /// <param name="str"></param>
535         /// <returns></returns>
536         public SmsMultiSenderResult ResponseStrToMultiSenderResult(string str)
537         {
538             SmsMultiSenderResult result = JsonConvert.DeserializeObject<SmsMultiSenderResult>(str);
539             return result;
540         }
541         #endregion
542
543         #region List<string>转JArray
544         /// <summary>
545         /// List<string>转JArray
546         /// </summary>
547         /// <param name="templParams"></param>
548         /// <returns></returns>
549         public JArray SmsParamsToJSONArray(List<string> templParams)
550         {
551             JArray smsParams = new JArray();
552             foreach (string templParamsElement in templParams)
553             {
554                 smsParams.Add(templParamsElement);
555             }
556             return smsParams;
557         }
558         #endregion
559
560         #region PhoneNumbersToJSONArray
561         /// <summary>
562         /// PhoneNumbersToJSONArray
563         /// </summary>
564         /// <param name="nationCode"></param>
565         /// <param name="phoneNumbers"></param>
566         /// <returns></returns>
567         public JArray PhoneNumbersToJSONArray(string nationCode, List<string> phoneNumbers)
568         {
569             JArray tel = new JArray();
570             int i = 0;
571             do
572             {
573                 JObject telElement = new JObject();
574                 telElement.Add("nationcode", nationCode);
575                 telElement.Add("mobile", phoneNumbers.ElementAt(i));
576                 tel.Add(telElement);
577             } while (++i < phoneNumbers.Count);
578             return tel;
579         }
580         #endregion
581
582         #region 计算App凭证
583         /*
584          "sig" 字段根据公式 sha256(appkey=$appkey&random=$random&time=$time&mobile=$mobile)生成
585          */
586         public string CalculateSigForTempl(string appkey, long random, long curTime, List<string> phoneNumbers)
587         {
588             string phoneNumbersString = phoneNumbers.ElementAt(0);
589             for (int i = 1; i < phoneNumbers.Count; i++)
590             {
591                 phoneNumbersString += "," + phoneNumbers.ElementAt(i);
592             }
593             return StrToHash(String.Format(
594                 "appkey={0}&random={1}&time={2}&mobile={3}",
595                 appkey, random, curTime, phoneNumbersString));
596         }
597
598         public string CalculateSigForTempl(string appkey, long random, long curTime, string phoneNumber)
599         {
600             List<string> phoneNumbers = new List<string>();
601             phoneNumbers.Add(phoneNumber);
602             return CalculateSigForTempl(appkey, random, curTime, phoneNumbers);
603         }
604
605         public string CalculateSig(string appkey, long random, long curTime, List<string> phoneNumbers)
606         {
607             string phoneNumbersString = phoneNumbers.ElementAt(0);
608             for (int i = 1; i < phoneNumbers.Count; i++)
609             {
610                 phoneNumbersString += "," + phoneNumbers.ElementAt(i);
611             }
612             return StrToHash(String.Format(
613                     "appkey={0}&random={1}&time={2}&mobile={3}",
614                     appkey, random, curTime, phoneNumbersString));
615         }
616         #endregion
617     }
618     #endregion
619 }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

demo下载路径为:https://files.cnblogs.com/files/LikeHeart/ConsoleTest.zip

Windows操作系统下Redis服务安装图文详解

Redis下载地址:https://github.com/MSOpenTech/redis/releases

下载msi格式的安装文件。

1.运行安装程序,单击next按钮。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

2.勾选接受许可协议中的条款,单击next按钮。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

3.选择安装目录,勾选添加到环境变量,单击next按钮。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

4.端口号以及防火墙添加例外,单击next按钮。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

5.是否设置最大内存限制,默认不勾选,单击next按钮。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

6.开始安装,单击Insatll按钮。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

7.等待安装,耗时不超过一分钟。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

8.安装完成,单击Finsh按钮。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

9.安装目录文件如下所示。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

10.可以从服务中查看到redis服务已经正常运行。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

Redis入门学习

一、软件安装

Redis下载地址:https://github.com/MSOpenTech/redis/releases

因为官方并不支持windows系统,需要从微软的GitHub上下载。

解压缩后文件夹内容如图所示(版本3.2.100):

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

最开始会用到的文件有redis-server.exe、redis-cli.exe以及一个配置文件redis.windows.conf。

1)启动redis服务,运行cmd.exe

进入到redis文件夹

cd desttop/redis

启动redis-server.exe 并使用配置文件,出现如下图所示就是启动成功了。

redis-server.exe redis.windows.conf

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

2)启动客户端,再打开一个cmd.exe

进入到文件夹后启动redis-cli.exe

redis-cli.exe

国际惯例,ping helloworld ,解锁熟练掌握redis的成就。

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

3)为什么默认使用6379端口

Redis作者antirez同学在twitter上说将在下一篇博文(http://oldblog.antirez.com/post/redis-as-LRU-cache.html)中向大家解释为什么他选择6379作为默认端口号。而现在这篇博文出炉,在解释了Redis的LRU机制之后,如期向大家解释了采用6379作为默认端口的原因。6379在是手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。

二、基本用法

redis是以kev-value形式进行数据存储的,value有字符串、哈希表、列表、集合、有序集合等。

一些命令的使用,可以参考http://doc.redisfans.com/学习。

配置文件的使用,redis.windows-service.conf(以windows服务运行时修改),

1.密码修改# requirepass foobared //去掉注释#,将foobared替换为你自己的密码2.文件命名修改dbfilename dump.rdb // xxxx.rdb

三、C#使用Redis

1)使用到的第三方dll:

<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
<package id="StackExchange.Redis" version="1.2.6" targetFramework="net45" />

2)搜集到的RedisHelper方法,增加了批量操作

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
   1 /// <summary>
   2     /// Redis操作
   3     /// </summary>
   4     public class RedisHelper
   5     {
   6         /// <summary>
   7         /// 连接redis库的Number
   8         /// </summary>
   9         private int DbNum { set; get; }
  10         private readonly ConnectionMultiplexer _conn;
  11         /// <summary>
  12         /// 自定义键前缀
  13         /// </summary>
  14         public string CustomKey;
  15
  16         #region 构造函数
  17
  18         public RedisHelper(int dbNum = 0)
  19             : this(dbNum, null)
  20         {
  21         }
  22
  23         public RedisHelper(int dbNum, string readWriteHosts)
  24         {
  25             DbNum = dbNum;
  26             _conn =
  27                 string.IsNullOrWhiteSpace(readWriteHosts) ?
  28                 RedisConnectionHelp.Instance :
  29                 RedisConnectionHelp.GetConnectionMultiplexer(readWriteHosts);
  30         }
  31
  32         #endregion 构造函数
  33
  34         #region String
  35
  36         #region 同步方法
  37
  38         /// <summary>
  39         /// 保存单个key value
  40         /// </summary>
  41         /// <param name="key">Redis Key</param>
  42         /// <param name="value">保存的值</param>
  43         /// <param name="expiry">过期时间</param>
  44         /// <returns></returns>
  45         public bool StringSet(string key, string value, TimeSpan? expiry = default(TimeSpan?))
  46         {
  47             key = AddSysCustomKey(key);
  48             return Do(db => db.StringSet(key, value, expiry));
  49         }
  50
  51         /// <summary>
  52         /// 保存多个key value
  53         /// </summary>
  54         /// <param name="keyValues">键值对</param>
  55         /// <returns></returns>
  56         public bool StringSet(List<KeyValuePair<RedisKey, RedisValue>> keyValues)
  57         {
  58             List<KeyValuePair<RedisKey, RedisValue>> newkeyValues =
  59                 keyValues.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToList();
  60             return Do(db => db.StringSet(newkeyValues.ToArray()));
  61         }
  62
  63         /// <summary>
  64         /// 保存一个对象
  65         /// </summary>
  66         /// <typeparam name="T"></typeparam>
  67         /// <param name="key"></param>
  68         /// <param name="obj"></param>
  69         /// <param name="expiry"></param>
  70         /// <returns></returns>
  71         public bool StringSet<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
  72         {
  73             key = AddSysCustomKey(key);
  74             string json = ConvertJson(obj);
  75             return Do(db => db.StringSet(key, json, expiry));
  76         }
  77
  78         /// <summary>
  79         /// 获取单个key的值
  80         /// </summary>
  81         /// <param name="key">Redis Key</param>
  82         /// <returns></returns>
  83         public byte[] StringGet(string key)
  84         {
  85             key = AddSysCustomKey(key);
  86             return Do(db => db.StringGet(key));
  87         }
  88
  89         /// <summary>
  90         /// 获取多个Key
  91         /// </summary>
  92         /// <param name="listKey">Redis Key集合</param>
  93         /// <returns></returns>
  94         public RedisValue[] StringGet(List<string> listKey)
  95         {
  96             List<string> newKeys = listKey.Select(AddSysCustomKey).ToList();
  97             return Do(db => db.StringGet(ConvertRedisKeys(newKeys)));
  98         }
  99
 100         /// <summary>
 101         /// 获取一个key的对象
 102         /// </summary>
 103         /// <typeparam name="T"></typeparam>
 104         /// <param name="key"></param>
 105         /// <returns></returns>
 106         public T StringGet<T>(string key)
 107         {
 108             key = AddSysCustomKey(key);
 109             return Do(db => ConvertObj<T>(db.StringGet(key)));
 110         }
 111
 112         public object StringGetObj(string key)
 113         {
 114             key = AddSysCustomKey(key);
 115             var database = _conn.GetDatabase(DbNum);
 116             return database.StringGet(key);
 117         }
 118
 119         public static object GetObjFromBytes(byte[] buffer)
 120         {
 121             using (System.IO.MemoryStream stream = new System.IO.MemoryStream(buffer))
 122             {
 123                 stream.Position = 0;
 124                 System.Runtime.Serialization.IFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
 125                 Object reobj = bf.Deserialize(stream);
 126                 return reobj;
 127             }
 128         }
 129
 130         /// <summary>
 131         /// 为数字增长val
 132         /// </summary>
 133         /// <param name="key"></param>
 134         /// <param name="val">可以为负</param>
 135         /// <returns>增长后的值</returns>
 136         public double StringIncrement(string key, double val = 1)
 137         {
 138             key = AddSysCustomKey(key);
 139             return Do(db => db.StringIncrement(key, val));
 140         }
 141
 142         /// <summary>
 143         /// 为数字减少val
 144         /// </summary>
 145         /// <param name="key"></param>
 146         /// <param name="val">可以为负</param>
 147         /// <returns>减少后的值</returns>
 148         public double StringDecrement(string key, double val = 1)
 149         {
 150             key = AddSysCustomKey(key);
 151             return Do(db => db.StringDecrement(key, val));
 152         }
 153
 154         #endregion 同步方法
 155
 156         #region 异步方法
 157
 158         /// <summary>
 159         /// 保存单个key value
 160         /// </summary>
 161         /// <param name="key">Redis Key</param>
 162         /// <param name="value">保存的值</param>
 163         /// <param name="expiry">过期时间</param>
 164         /// <returns></returns>
 165         public async Task<bool> StringSetAsync(string key, string value, TimeSpan? expiry = default(TimeSpan?))
 166         {
 167             key = AddSysCustomKey(key);
 168             return await Do(db => db.StringSetAsync(key, value, expiry));
 169         }
 170
 171         /// <summary>
 172         /// 保存多个key value
 173         /// </summary>
 174         /// <param name="keyValues">键值对</param>
 175         /// <returns></returns>
 176         public async Task<bool> StringSetAsync(List<KeyValuePair<RedisKey, RedisValue>> keyValues)
 177         {
 178             List<KeyValuePair<RedisKey, RedisValue>> newkeyValues =
 179                 keyValues.Select(p => new KeyValuePair<RedisKey, RedisValue>(AddSysCustomKey(p.Key), p.Value)).ToList();
 180             return await Do(db => db.StringSetAsync(newkeyValues.ToArray()));
 181         }
 182
 183         /// <summary>
 184         /// 保存一个对象
 185         /// </summary>
 186         /// <typeparam name="T"></typeparam>
 187         /// <param name="key"></param>
 188         /// <param name="obj"></param>
 189         /// <param name="expiry"></param>
 190         /// <returns></returns>
 191         public async Task<bool> StringSetAsync<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
 192         {
 193             key = AddSysCustomKey(key);
 194             string json = ConvertJson(obj);
 195             return await Do(db => db.StringSetAsync(key, json, expiry));
 196         }
 197
 198         /// <summary>
 199         /// 获取单个key的值
 200         /// </summary>
 201         /// <param name="key">Redis Key</param>
 202         /// <returns></returns>
 203         public async Task<string> StringGetAsync(string key)
 204         {
 205             key = AddSysCustomKey(key);
 206             return await Do(db => db.StringGetAsync(key));
 207         }
 208
 209         /// <summary>
 210         /// 获取多个Key
 211         /// </summary>
 212         /// <param name="listKey">Redis Key集合</param>
 213         /// <returns></returns>
 214         public async Task<RedisValue[]> StringGetAsync(List<string> listKey)
 215         {
 216             List<string> newKeys = listKey.Select(AddSysCustomKey).ToList();
 217             return await Do(db => db.StringGetAsync(ConvertRedisKeys(newKeys)));
 218         }
 219
 220         /// <summary>
 221         /// 获取一个key的对象
 222         /// </summary>
 223         /// <typeparam name="T"></typeparam>
 224         /// <param name="key"></param>
 225         /// <returns></returns>
 226         public async Task<T> StringGetAsync<T>(string key)
 227         {
 228             key = AddSysCustomKey(key);
 229             string result = await Do(db => db.StringGetAsync(key));
 230             return ConvertObj<T>(result);
 231         }
 232
 233         /// <summary>
 234         /// 为数字增长val
 235         /// </summary>
 236         /// <param name="key"></param>
 237         /// <param name="val">可以为负</param>
 238         /// <returns>增长后的值</returns>
 239         public async Task<double> StringIncrementAsync(string key, double val = 1)
 240         {
 241             key = AddSysCustomKey(key);
 242             return await Do(db => db.StringIncrementAsync(key, val));
 243         }
 244
 245         /// <summary>
 246         /// 为数字减少val
 247         /// </summary>
 248         /// <param name="key"></param>
 249         /// <param name="val">可以为负</param>
 250         /// <returns>减少后的值</returns>
 251         public async Task<double> StringDecrementAsync(string key, double val = 1)
 252         {
 253             key = AddSysCustomKey(key);
 254             return await Do(db => db.StringDecrementAsync(key, val));
 255         }
 256
 257         #endregion 异步方法
 258
 259         #endregion String
 260
 261         #region Hash
 262
 263         #region 同步方法
 264
 265         /// <summary>
 266         /// 判断某个数据是否已经被缓存
 267         /// </summary>
 268         /// <param name="key"></param>
 269         /// <param name="dataKey"></param>
 270         /// <returns></returns>
 271         public bool HashExists(string key, string dataKey)
 272         {
 273             key = AddSysCustomKey(key);
 274             return Do(db => db.HashExists(key, dataKey));
 275         }
 276
 277         /// <summary>
 278         /// 存储数据到hash表
 279         /// </summary>
 280         /// <typeparam name="T"></typeparam>
 281         /// <param name="key"></param>
 282         /// <param name="dataKey"></param>
 283         /// <param name="t"></param>
 284         /// <returns></returns>
 285         public bool HashSet<T>(string key, string dataKey, T t)
 286         {
 287             key = AddSysCustomKey(key);
 288             return Do(db =>
 289             {
 290                 string json = ConvertJson(t);
 291                 return db.HashSet(key, dataKey, json);
 292             });
 293         }
 294
 295         /// <summary>
 296         /// 移除hash中的某值
 297         /// </summary>
 298         /// <param name="key"></param>
 299         /// <param name="dataKey"></param>
 300         /// <returns></returns>
 301         public bool HashDelete(string key, string dataKey)
 302         {
 303             key = AddSysCustomKey(key);
 304             return Do(db => db.HashDelete(key, dataKey));
 305         }
 306
 307         /// <summary>
 308         /// 移除hash中的多个值
 309         /// </summary>
 310         /// <param name="key"></param>
 311         /// <param name="dataKeys"></param>
 312         /// <returns></returns>
 313         public long HashDelete(string key, List<RedisValue> dataKeys)
 314         {
 315             key = AddSysCustomKey(key);
 316             //List<RedisValue> dataKeys1 = new List<RedisValue>() {"1","2"};
 317             return Do(db => db.HashDelete(key, dataKeys.ToArray()));
 318         }
 319
 320         /// <summary>
 321         /// 从hash表获取数据
 322         /// </summary>
 323         /// <typeparam name="T"></typeparam>
 324         /// <param name="key"></param>
 325         /// <param name="dataKey"></param>
 326         /// <returns></returns>
 327         public T HashGet<T>(string key, string dataKey)
 328         {
 329             key = AddSysCustomKey(key);
 330             return Do(db =>
 331             {
 332                 string value = db.HashGet(key, dataKey);
 333                 return ConvertObj<T>(value);
 334             });
 335         }
 336
 337         /// <summary>
 338         /// 为数字增长val
 339         /// </summary>
 340         /// <param name="key"></param>
 341         /// <param name="dataKey"></param>
 342         /// <param name="val">可以为负</param>
 343         /// <returns>增长后的值</returns>
 344         public double HashIncrement(string key, string dataKey, double val = 1)
 345         {
 346             key = AddSysCustomKey(key);
 347             return Do(db => db.HashIncrement(key, dataKey, val));
 348         }
 349
 350         /// <summary>
 351         /// 为数字减少val
 352         /// </summary>
 353         /// <param name="key"></param>
 354         /// <param name="dataKey"></param>
 355         /// <param name="val">可以为负</param>
 356         /// <returns>减少后的值</returns>
 357         public double HashDecrement(string key, string dataKey, double val = 1)
 358         {
 359             key = AddSysCustomKey(key);
 360             return Do(db => db.HashDecrement(key, dataKey, val));
 361         }
 362
 363         /// <summary>
 364         /// 获取hashkey所有Redis key
 365         /// </summary>
 366         /// <typeparam name="T"></typeparam>
 367         /// <param name="key"></param>
 368         /// <returns></returns>
 369         public List<T> HashKeys<T>(string key)
 370         {
 371             key = AddSysCustomKey(key);
 372             return Do(db =>
 373             {
 374                 RedisValue[] values = db.HashKeys(key);
 375                 return ConvetList<T>(values);
 376             });
 377         }
 378
 379         #endregion 同步方法
 380
 381         #region 异步方法
 382
 383         /// <summary>
 384         /// 判断某个数据是否已经被缓存
 385         /// </summary>
 386         /// <param name="key"></param>
 387         /// <param name="dataKey"></param>
 388         /// <returns></returns>
 389         public async Task<bool> HashExistsAsync(string key, string dataKey)
 390         {
 391             key = AddSysCustomKey(key);
 392             return await Do(db => db.HashExistsAsync(key, dataKey));
 393         }
 394
 395         /// <summary>
 396         /// 存储数据到hash表
 397         /// </summary>
 398         /// <typeparam name="T"></typeparam>
 399         /// <param name="key"></param>
 400         /// <param name="dataKey"></param>
 401         /// <param name="t"></param>
 402         /// <returns></returns>
 403         public async Task<bool> HashSetAsync<T>(string key, string dataKey, T t)
 404         {
 405             key = AddSysCustomKey(key);
 406             return await Do(db =>
 407             {
 408                 string json = ConvertJson(t);
 409                 return db.HashSetAsync(key, dataKey, json);
 410             });
 411         }
 412
 413         /// <summary>
 414         /// 移除hash中的某值
 415         /// </summary>
 416         /// <param name="key"></param>
 417         /// <param name="dataKey"></param>
 418         /// <returns></returns>
 419         public async Task<bool> HashDeleteAsync(string key, string dataKey)
 420         {
 421             key = AddSysCustomKey(key);
 422             return await Do(db => db.HashDeleteAsync(key, dataKey));
 423         }
 424
 425         /// <summary>
 426         /// 移除hash中的多个值
 427         /// </summary>
 428         /// <param name="key"></param>
 429         /// <param name="dataKeys"></param>
 430         /// <returns></returns>
 431         public async Task<long> HashDeleteAsync(string key, List<RedisValue> dataKeys)
 432         {
 433             key = AddSysCustomKey(key);
 434             //List<RedisValue> dataKeys1 = new List<RedisValue>() {"1","2"};
 435             return await Do(db => db.HashDeleteAsync(key, dataKeys.ToArray()));
 436         }
 437
 438         /// <summary>
 439         /// 从hash表获取数据
 440         /// </summary>
 441         /// <typeparam name="T"></typeparam>
 442         /// <param name="key"></param>
 443         /// <param name="dataKey"></param>
 444         /// <returns></returns>
 445         public async Task<T> HashGeAsync<T>(string key, string dataKey)
 446         {
 447             key = AddSysCustomKey(key);
 448             string value = await Do(db => db.HashGetAsync(key, dataKey));
 449             return ConvertObj<T>(value);
 450         }
 451
 452         /// <summary>
 453         /// 为数字增长val
 454         /// </summary>
 455         /// <param name="key"></param>
 456         /// <param name="dataKey"></param>
 457         /// <param name="val">可以为负</param>
 458         /// <returns>增长后的值</returns>
 459         public async Task<double> HashIncrementAsync(string key, string dataKey, double val = 1)
 460         {
 461             key = AddSysCustomKey(key);
 462             return await Do(db => db.HashIncrementAsync(key, dataKey, val));
 463         }
 464
 465         /// <summary>
 466         /// 为数字减少val
 467         /// </summary>
 468         /// <param name="key"></param>
 469         /// <param name="dataKey"></param>
 470         /// <param name="val">可以为负</param>
 471         /// <returns>减少后的值</returns>
 472         public async Task<double> HashDecrementAsync(string key, string dataKey, double val = 1)
 473         {
 474             key = AddSysCustomKey(key);
 475             return await Do(db => db.HashDecrementAsync(key, dataKey, val));
 476         }
 477
 478         /// <summary>
 479         /// 获取hashkey所有Redis key
 480         /// </summary>
 481         /// <typeparam name="T"></typeparam>
 482         /// <param name="key"></param>
 483         /// <returns></returns>
 484         public async Task<List<T>> HashKeysAsync<T>(string key)
 485         {
 486             key = AddSysCustomKey(key);
 487             RedisValue[] values = await Do(db => db.HashKeysAsync(key));
 488             return ConvetList<T>(values);
 489         }
 490
 491         #endregion 异步方法
 492
 493         #endregion Hash
 494
 495         #region List
 496
 497         #region 同步方法
 498
 499         /// <summary>
 500         /// 移除指定ListId的内部List的值
 501         /// </summary>
 502         /// <param name="key"></param>
 503         /// <param name="value"></param>
 504         public void ListRemove<T>(string key, T value)
 505         {
 506             key = AddSysCustomKey(key);
 507             Do(db => db.ListRemove(key, ConvertJson(value)));
 508         }
 509
 510         /// <summary>
 511         /// 获取指定key的List
 512         /// </summary>
 513         /// <param name="key"></param>
 514         /// <returns></returns>
 515         public List<T> ListRange<T>(string key)
 516         {
 517             key = AddSysCustomKey(key);
 518             return Do(redis =>
 519             {
 520                 var values = redis.ListRange(key);
 521                 return ConvetList<T>(values);
 522             });
 523         }
 524
 525         /// <summary>
 526         /// 入队
 527         /// </summary>
 528         /// <param name="key"></param>
 529         /// <param name="value"></param>
 530         public void ListRightPush<T>(string key, T value)
 531         {
 532             key = AddSysCustomKey(key);
 533             Do(db => db.ListRightPush(key, ConvertJson(value)));
 534         }
 535
 536         /// <summary>
 537         /// 出队
 538         /// </summary>
 539         /// <typeparam name="T"></typeparam>
 540         /// <param name="key"></param>
 541         /// <returns></returns>
 542         public T ListRightPop<T>(string key)
 543         {
 544             key = AddSysCustomKey(key);
 545             return Do(db =>
 546              {
 547                  var value = db.ListRightPop(key);
 548                  return ConvertObj<T>(value);
 549              });
 550         }
 551
 552         /// <summary>
 553         /// 入栈
 554         /// </summary>
 555         /// <typeparam name="T"></typeparam>
 556         /// <param name="key"></param>
 557         /// <param name="value"></param>
 558         public void ListLeftPush<T>(string key, T value)
 559         {
 560             key = AddSysCustomKey(key);
 561             Do(db => db.ListLeftPush(key, ConvertJson(value)));
 562         }
 563
 564         /// <summary>
 565         /// 出栈
 566         /// </summary>
 567         /// <typeparam name="T"></typeparam>
 568         /// <param name="key"></param>
 569         /// <returns></returns>
 570         public T ListLeftPop<T>(string key)
 571         {
 572             key = AddSysCustomKey(key);
 573             return Do(db =>
 574             {
 575                 var value = db.ListLeftPop(key);
 576                 return ConvertObj<T>(value);
 577             });
 578         }
 579
 580         /// <summary>
 581         /// 获取集合中的数量
 582         /// </summary>
 583         /// <param name="key"></param>
 584         /// <returns></returns>
 585         public long ListLength(string key)
 586         {
 587             key = AddSysCustomKey(key);
 588             return Do(redis => redis.ListLength(key));
 589         }
 590
 591         #endregion 同步方法
 592
 593         #region 异步方法
 594
 595         /// <summary>
 596         /// 移除指定ListId的内部List的值
 597         /// </summary>
 598         /// <param name="key"></param>
 599         /// <param name="value"></param>
 600         public async Task<long> ListRemoveAsync<T>(string key, T value)
 601         {
 602             key = AddSysCustomKey(key);
 603             return await Do(db => db.ListRemoveAsync(key, ConvertJson(value)));
 604         }
 605
 606         /// <summary>
 607         /// 获取指定key的List
 608         /// </summary>
 609         /// <param name="key"></param>
 610         /// <returns></returns>
 611         public async Task<List<T>> ListRangeAsync<T>(string key)
 612         {
 613             key = AddSysCustomKey(key);
 614             var values = await Do(redis => redis.ListRangeAsync(key));
 615             return ConvetList<T>(values);
 616         }
 617
 618         /// <summary>
 619         /// 入队
 620         /// </summary>
 621         /// <param name="key"></param>
 622         /// <param name="value"></param>
 623         public async Task<long> ListRightPushAsync<T>(string key, T value)
 624         {
 625             key = AddSysCustomKey(key);
 626             return await Do(db => db.ListRightPushAsync(key, ConvertJson(value)));
 627         }
 628
 629         /// <summary>
 630         /// 出队
 631         /// </summary>
 632         /// <typeparam name="T"></typeparam>
 633         /// <param name="key"></param>
 634         /// <returns></returns>
 635         public async Task<T> ListRightPopAsync<T>(string key)
 636         {
 637             key = AddSysCustomKey(key);
 638             var value = await Do(db => db.ListRightPopAsync(key));
 639             return ConvertObj<T>(value);
 640         }
 641
 642         /// <summary>
 643         /// 入栈
 644         /// </summary>
 645         /// <typeparam name="T"></typeparam>
 646         /// <param name="key"></param>
 647         /// <param name="value"></param>
 648         public async Task<long> ListLeftPushAsync<T>(string key, T value)
 649         {
 650             key = AddSysCustomKey(key);
 651             return await Do(db => db.ListLeftPushAsync(key, ConvertJson(value)));
 652         }
 653
 654         /// <summary>
 655         /// 出栈
 656         /// </summary>
 657         /// <typeparam name="T"></typeparam>
 658         /// <param name="key"></param>
 659         /// <returns></returns>
 660         public async Task<T> ListLeftPopAsync<T>(string key)
 661         {
 662             key = AddSysCustomKey(key);
 663             var value = await Do(db => db.ListLeftPopAsync(key));
 664             return ConvertObj<T>(value);
 665         }
 666
 667         /// <summary>
 668         /// 获取集合中的数量
 669         /// </summary>
 670         /// <param name="key"></param>
 671         /// <returns></returns>
 672         public async Task<long> ListLengthAsync(string key)
 673         {
 674             key = AddSysCustomKey(key);
 675             return await Do(redis => redis.ListLengthAsync(key));
 676         }
 677
 678         #endregion 异步方法
 679
 680         #endregion List
 681
 682         #region SortedSet 有序集合
 683
 684         #region 同步方法
 685
 686         /// <summary>
 687         /// 添加
 688         /// </summary>
 689         /// <param name="key"></param>
 690         /// <param name="value"></param>
 691         /// <param name="score"></param>
 692         public bool SortedSetAdd<T>(string key, T value, double score)
 693         {
 694             key = AddSysCustomKey(key);
 695             return Do(redis => redis.SortedSetAdd(key, ConvertJson<T>(value), score));
 696         }
 697
 698         /// <summary>
 699         /// 删除
 700         /// </summary>
 701         /// <param name="key"></param>
 702         /// <param name="value"></param>
 703         public bool SortedSetRemove<T>(string key, T value)
 704         {
 705             key = AddSysCustomKey(key);
 706             return Do(redis => redis.SortedSetRemove(key, ConvertJson(value)));
 707         }
 708
 709         /// <summary>
 710         /// 获取全部
 711         /// </summary>
 712         /// <param name="key"></param>
 713         /// <returns></returns>
 714         public List<T> SortedSetRangeByRank<T>(string key)
 715         {
 716             key = AddSysCustomKey(key);
 717             return Do(redis =>
 718             {
 719                 var values = redis.SortedSetRangeByRank(key);
 720                 return ConvetList<T>(values);
 721             });
 722         }
 723
 724         /// <summary>
 725         /// 获取集合中的数量
 726         /// </summary>
 727         /// <param name="key"></param>
 728         /// <returns></returns>
 729         public long SortedSetLength(string key)
 730         {
 731             key = AddSysCustomKey(key);
 732             return Do(redis => redis.SortedSetLength(key));
 733         }
 734
 735         #endregion 同步方法
 736
 737         #region 异步方法
 738
 739         /// <summary>
 740         /// 添加
 741         /// </summary>
 742         /// <param name="key"></param>
 743         /// <param name="value"></param>
 744         /// <param name="score"></param>
 745         public async Task<bool> SortedSetAddAsync<T>(string key, T value, double score)
 746         {
 747             key = AddSysCustomKey(key);
 748             return await Do(redis => redis.SortedSetAddAsync(key, ConvertJson<T>(value), score));
 749         }
 750
 751         /// <summary>
 752         /// 删除
 753         /// </summary>
 754         /// <param name="key"></param>
 755         /// <param name="value"></param>
 756         public async Task<bool> SortedSetRemoveAsync<T>(string key, T value)
 757         {
 758             key = AddSysCustomKey(key);
 759             return await Do(redis => redis.SortedSetRemoveAsync(key, ConvertJson(value)));
 760         }
 761
 762         /// <summary>
 763         /// 获取全部
 764         /// </summary>
 765         /// <param name="key"></param>
 766         /// <returns></returns>
 767         public async Task<List<T>> SortedSetRangeByRankAsync<T>(string key)
 768         {
 769             key = AddSysCustomKey(key);
 770             var values = await Do(redis => redis.SortedSetRangeByRankAsync(key));
 771             return ConvetList<T>(values);
 772         }
 773
 774         /// <summary>
 775         /// 获取集合中的数量
 776         /// </summary>
 777         /// <param name="key"></param>
 778         /// <returns></returns>
 779         public async Task<long> SortedSetLengthAsync(string key)
 780         {
 781             key = AddSysCustomKey(key);
 782             return await Do(redis => redis.SortedSetLengthAsync(key));
 783         }
 784
 785         #endregion 异步方法
 786
 787         #endregion SortedSet 有序集合
 788
 789         #region key
 790
 791         /// <summary>
 792         /// 删除单个key
 793         /// </summary>
 794         /// <param name="key">redis key</param>
 795         /// <returns>是否删除成功</returns>
 796         public bool KeyDelete(string key)
 797         {
 798             key = AddSysCustomKey(key);
 799             return Do(db => db.KeyDelete(key));
 800         }
 801
 802         /// <summary>
 803         /// 删除多个key
 804         /// </summary>
 805         /// <param name="keys">rediskey</param>
 806         /// <returns>成功删除的个数</returns>
 807         public long KeyDelete(List<string> keys)
 808         {
 809             List<string> newKeys = keys.Select(AddSysCustomKey).ToList();
 810             return Do(db => db.KeyDelete(ConvertRedisKeys(newKeys)));
 811         }
 812
 813         /// <summary>
 814         /// 判断key是否存储
 815         /// </summary>
 816         /// <param name="key">redis key</param>
 817         /// <returns></returns>
 818         public bool KeyExists(string key)
 819         {
 820             key = AddSysCustomKey(key);
 821             return Do(db => db.KeyExists(key));
 822         }
 823
 824         /// <summary>
 825         /// 重新命名key
 826         /// </summary>
 827         /// <param name="key">就的redis key</param>
 828         /// <param name="newKey">新的redis key</param>
 829         /// <returns></returns>
 830         public bool KeyRename(string key, string newKey)
 831         {
 832             key = AddSysCustomKey(key);
 833             return Do(db => db.KeyRename(key, newKey));
 834         }
 835
 836         /// <summary>
 837         /// 设置Key的时间
 838         /// </summary>
 839         /// <param name="key">redis key</param>
 840         /// <param name="expiry"></param>
 841         /// <returns></returns>
 842         public bool KeyExpire(string key, TimeSpan? expiry = default(TimeSpan?))
 843         {
 844             key = AddSysCustomKey(key);
 845             return Do(db => db.KeyExpire(key, expiry));
 846         }
 847
 848         #endregion key
 849
 850         #region 发布订阅
 851
 852         /// <summary>
 853         /// Redis发布订阅  订阅
 854         /// </summary>
 855         /// <param name="subChannel"></param>
 856         /// <param name="handler"></param>
 857         public void Subscribe(string subChannel, Action<RedisChannel, RedisValue> handler = null)
 858         {
 859             ISubscriber sub = _conn.GetSubscriber();
 860             sub.Subscribe(subChannel, (channel, message) =>
 861             {
 862                 if (handler == null)
 863                 {
 864                     Console.WriteLine(subChannel + " 订阅收到消息:" + message);
 865                 }
 866                 else
 867                 {
 868                     handler(channel, message);
 869                 }
 870             });
 871         }
 872
 873         /// <summary>
 874         /// Redis发布订阅  发布
 875         /// </summary>
 876         /// <typeparam name="T"></typeparam>
 877         /// <param name="channel"></param>
 878         /// <param name="msg"></param>
 879         /// <returns></returns>
 880         public long Publish<T>(string channel, T msg)
 881         {
 882             ISubscriber sub = _conn.GetSubscriber();
 883             return sub.Publish(channel, ConvertJson(msg));
 884         }
 885
 886         /// <summary>
 887         /// Redis发布订阅  取消订阅
 888         /// </summary>
 889         /// <param name="channel"></param>
 890         public void Unsubscribe(string channel)
 891         {
 892             ISubscriber sub = _conn.GetSubscriber();
 893             sub.Unsubscribe(channel);
 894         }
 895
 896         /// <summary>
 897         /// Redis发布订阅  取消全部订阅
 898         /// </summary>
 899         public void UnsubscribeAll()
 900         {
 901             ISubscriber sub = _conn.GetSubscriber();
 902             sub.UnsubscribeAll();
 903         }
 904
 905         #endregion 发布订阅
 906
 907         #region 其他
 908
 909         public ITransaction CreateTransaction()
 910         {
 911             return GetDatabase().CreateTransaction();
 912         }
 913
 914         public IDatabase GetDatabase()
 915         {
 916             return _conn.GetDatabase(DbNum);
 917         }
 918
 919         public IServer GetServer(string hostAndPort)
 920         {
 921             return _conn.GetServer(hostAndPort);
 922         }
 923
 924         /// <summary>
 925         /// 设置前缀
 926         /// </summary>
 927         /// <param name="customKey"></param>
 928         public void SetSysCustomKey(string customKey)
 929         {
 930             CustomKey = customKey;
 931         }
 932
 933         #endregion 其他
 934
 935         #region 辅助方法
 936
 937         private string AddSysCustomKey(string oldKey)
 938         {
 939             var prefixKey = CustomKey ?? RedisConnectionHelp.SysCustomKey;
 940             return prefixKey + oldKey;
 941         }
 942
 943         private T Do<T>(Func<IDatabase, T> func)
 944         {
 945             var database = _conn.GetDatabase(DbNum);
 946             return func(database);
 947         }
 948
 949         public string ConvertJson<T>(T value)
 950         {
 951             string result = value is string ? value.ToString() : JsonConvert.SerializeObject(value);
 952             return result;
 953         }
 954
 955         public T ConvertObj<T>(RedisValue value)
 956         {
 957             return JsonConvert.DeserializeObject<T>(value);
 958         }
 959
 960         private List<T> ConvetList<T>(RedisValue[] values)
 961         {
 962             List<T> result = new List<T>();
 963             foreach (var item in values)
 964             {
 965                 var model = ConvertObj<T>(item);
 966                 result.Add(model);
 967             }
 968             return result;
 969         }
 970
 971         private RedisKey[] ConvertRedisKeys(List<string> redisKeys)
 972         {
 973             return redisKeys.Select(redisKey => (RedisKey)redisKey).ToArray();
 974         }
 975
 976         #endregion 辅助方法
 977
 978         #region 批量操作
 979
 980         #region 批量写Key-Value
 981         /// <summary>
 982         /// 批量写Key-Value
 983         /// </summary>
 984         /// <param name="keyValues"></param>
 985         /// <returns></returns>
 986         public bool StringWriteBatch(List<KeyValuePair<RedisKey, RedisValue>> keyValues)
 987         {
 988             bool result = false;
 989             try
 990             {
 991                 var db = _conn.GetDatabase();
 992                 var batch = db.CreateBatch();
 993                 foreach (var item in keyValues)
 994                 {
 995                     batch.StringSetAsync(item.Key, item.Value);
 996                 }
 997                 batch.Execute();
 998                 result = true;
 999             }
1000             catch
1001             {
1002             }
1003             return result;
1004         }
1005         #endregion
1006
1007         #region 批量读Key-Value
1008         /// <summary>
1009         /// 批量读Key-Value
1010         /// </summary>
1011         /// <typeparam name="T"></typeparam>
1012         /// <param name="lstKey"></param>
1013         /// <returns></returns>
1014         public List<T> StringReadBatch<T>(List<RedisKey> lstKey)
1015         {
1016             List<Task<RedisValue>> valueList = new List<Task<RedisValue>>();
1017             List<T> lstResult = new List<T>();
1018             try
1019             {
1020                 var db = _conn.GetDatabase();
1021                 var batch = db.CreateBatch();
1022                 foreach (var item in lstKey)
1023                 {
1024                     Task<RedisValue> value = batch.StringGetAsync(item);
1025                     valueList.Add(value);
1026                 }
1027                 batch.Execute();
1028
1029                 foreach (var item in valueList)
1030                 {
1031                     T t = ConvertObj<T>(item.Result);
1032                     lstResult.Add(t);
1033                 }
1034             }
1035             catch
1036             {
1037             }
1038             return lstResult;
1039         }
1040
1041         /// <summary>
1042         /// 批量读操作,返回DataSe集合
1043         /// </summary>
1044         /// <param name="lstKey"></param>
1045         /// <returns></returns>
1046         public DataSet StringReadBatch(List<RedisKey> lstKey)
1047         {
1048             if (lstKey == null || lstKey.Count < 1) return null;
1049             List<Task<RedisValue>> valueList = new List<Task<RedisValue>>();
1050             DataSet ds = new DataSet();
1051             try
1052             {
1053                 var db = _conn.GetDatabase();
1054                 var batch = db.CreateBatch();
1055                 foreach (var item in lstKey)
1056                 {
1057                     Task<RedisValue> value = batch.StringGetAsync(item);
1058                     valueList.Add(value);
1059                 }
1060                 batch.Execute();
1061
1062                 foreach (var item in valueList)
1063                 {
1064                     DataTable t = ConvertObj<DataTable>(item.Result);
1065                     ds.Tables.Add(t);
1066                 }
1067             }
1068             catch
1069             {
1070             }
1071             return ds;
1072         }
1073         #endregion
1074
1075         #region 批量写Hash
1076         /// <summary>
1077         /// 批量写Hash
1078         /// </summary>
1079         /// <param name="keyValues"></param>
1080         /// <returns></returns>
1081         public bool HashWriteBatch(List<KeyValuePair<RedisKey, HashEntry[]>> keyValues)
1082         {
1083             bool result = false;
1084             try
1085             {
1086                 var db = _conn.GetDatabase();
1087                 var batch = db.CreateBatch();
1088                 foreach (var item in keyValues)
1089                 {
1090                     batch.HashSetAsync(item.Key, item.Value);
1091                 }
1092                 batch.Execute();
1093                 result = true;
1094             }
1095             catch
1096             {
1097             }
1098             return result;
1099         }
1100         #endregion
1101
1102         #region 批量读Hash
1103         /// <summary>
1104         /// 批量读Hash
1105         /// </summary>
1106         ///<param name="keyFields">hash键和field</param>
1107         /// <returns></returns>
1108         public List<T> HashReadBatch<T>(List<KeyValuePair<RedisKey, RedisValue[]>> keyFields)
1109         {
1110             List<Task<RedisValue[]>> valueList = new List<Task<RedisValue[]>>();
1111             List<T> lstResult = new List<T>();
1112             try
1113             {
1114                 var db = _conn.GetDatabase();
1115                 var batch = db.CreateBatch();
1116                 foreach (var item in keyFields)
1117                 {
1118                     Task<RedisValue[]> value = batch.HashGetAsync(item.Key, item.Value);
1119                     valueList.Add(value);
1120                 }
1121                 batch.Execute();
1122
1123                 foreach (var item in valueList)
1124                 {
1125                     if (item.Result == null) continue;
1126                     foreach (var redisValue in item.Result)
1127                     {
1128                         T t = ConvertObj<T>(redisValue);
1129                         lstResult.Add(t);
1130                     }
1131                 }
1132             }
1133             catch
1134             {
1135             }
1136             return lstResult;
1137         }
1138         #endregion
1139
1140         #endregion
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

3)单例模式

反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习
  1 /// <summary>
  2     /// ConnectionMultiplexer对象管理帮助类
  3     /// </summary>
  4     public static class RedisConnectionHelp
  5     {
  6         //系统自定义Key前缀
  7         public static readonly string SysCustomKey = ConfigurationManager.AppSettings["redisKey"] ?? "";
  8
  9         //"127.0.0.1:6379,allowadmin=true
 10         private static readonly string RedisConnectionString = ConfigurationManager.ConnectionStrings["RedisExchangeHosts"].ConnectionString;
 11
 12         private static readonly object Locker = new object();
 13         private static ConnectionMultiplexer _instance;
 14         private static readonly ConcurrentDictionary<string, ConnectionMultiplexer> ConnectionCache = new ConcurrentDictionary<string, ConnectionMultiplexer>();
 15
 16         /// <summary>
 17         /// 单例获取
 18         /// </summary>
 19         public static ConnectionMultiplexer Instance
 20         {
 21             get
 22             {
 23                 if (_instance == null)
 24                 {
 25                     lock (Locker)
 26                     {
 27                         if (_instance == null || !_instance.IsConnected)
 28                         {
 29                             _instance = GetManager();
 30                         }
 31                     }
 32                 }
 33                 return _instance;
 34             }
 35         }
 36
 37         /// <summary>
 38         /// 缓存获取
 39         /// </summary>
 40         /// <param name="connectionString"></param>
 41         /// <returns></returns>
 42         public static ConnectionMultiplexer GetConnectionMultiplexer(string connectionString)
 43         {
 44             if (!ConnectionCache.ContainsKey(connectionString))
 45             {
 46                 ConnectionCache[connectionString] = GetManager(connectionString);
 47             }
 48             return ConnectionCache[connectionString];
 49         }
 50
 51         private static ConnectionMultiplexer GetManager(string connectionString = null)
 52         {
 53             connectionString = connectionString ?? RedisConnectionString;
 54             var connect = ConnectionMultiplexer.Connect(connectionString);
 55
 56             //注册如下事件
 57             connect.ConnectionFailed += MuxerConnectionFailed;
 58             connect.ConnectionRestored += MuxerConnectionRestored;
 59             connect.ErrorMessage += MuxerErrorMessage;
 60             connect.ConfigurationChanged += MuxerConfigurationChanged;
 61             connect.HashSlotMoved += MuxerHashSlotMoved;
 62             connect.InternalError += MuxerInternalError;
 63
 64             return connect;
 65         }
 66
 67         #region 事件
 68
 69         /// <summary>
 70         /// 配置更改时
 71         /// </summary>
 72         /// <param name="sender"></param>
 73         /// <param name="e"></param>
 74         private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
 75         {
 76             Console.WriteLine("Configuration changed: " + e.EndPoint);
 77         }
 78
 79         /// <summary>
 80         /// 发生错误时
 81         /// </summary>
 82         /// <param name="sender"></param>
 83         /// <param name="e"></param>
 84         private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
 85         {
 86             Console.WriteLine("ErrorMessage: " + e.Message);
 87         }
 88
 89         /// <summary>
 90         /// 重新建立连接之前的错误
 91         /// </summary>
 92         /// <param name="sender"></param>
 93         /// <param name="e"></param>
 94         private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
 95         {
 96             Console.WriteLine("ConnectionRestored: " + e.EndPoint);
 97         }
 98
 99         /// <summary>
100         /// 连接失败 , 如果重新连接成功你将不会收到这个通知
101         /// </summary>
102         /// <param name="sender"></param>
103         /// <param name="e"></param>
104         private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
105         {
106             Console.WriteLine("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
107         }
108
109         /// <summary>
110         /// 更改集群
111         /// </summary>
112         /// <param name="sender"></param>
113         /// <param name="e"></param>
114         private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
115         {
116             Console.WriteLine("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
117         }
118
119         /// <summary>
120         /// redis类库错误
121         /// </summary>
122         /// <param name="sender"></param>
123         /// <param name="e"></param>
124         private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
125         {
126             Console.WriteLine("InternalError:Message" + e.Exception.Message);
127         }
128
129         #endregion 事件
130     }
反射实现Model修改前后的内容对比    【API调用】腾讯云短信    Windows操作系统下Redis服务安装图文详解    Redis入门学习

4)app.config中增加redis连接字符串

<connectionStrings>
    <add name="RedisExchangeHosts" connectionString="127.0.0.1:6379,password=xxxxxx"/>
</connectionStrings>