/// <summary> /// 发送命令给服务器 /// </summary> /// <param name="ns"></param> /// <param name="cmd"></param> /// <returns></returns> private bool Send(NetworkStream ns, RedisCommand cmd) { // 取得内存流对象 var ms = Cache.Get(); if (ms == null) { throw new RedisClientException(Cache.Message, MethodBase.GetCurrentMethod()); } // 制作命令包并将其写入内存流 // 说明:Redis的管道(pipelining)技术就是将不同命令打包在一起批量发送。 // 参考:https://redis.io/topics/pipelining try { // 取得并写入命令和参数,示例:*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n foreach (var obj in cmd.Value) { if (obj is byte[] byts) { ms.Write(byts, 0, byts.Length); } } } catch (Exception e) { throw new RedisClientException($"创建命令{ObjectConvert.C2Str(cmd.Command)}失败({e.Message})", MethodBase.GetCurrentMethod(), ObjectConvert.C2Str(ms.ToArray())); } // 尝试将内存流写入到网络流发送给服务器 try { ms.WriteTo(ns); } catch (Exception e) { throw new RedisClientException($"发送命令{ObjectConvert.C2Str(cmd.Command)}失败({e.Message})", MethodBase.GetCurrentMethod(), ObjectConvert.C2Str(ms.ToArray())); } finally { // 归还内存流对象 Cache.Put(ms); } // 返回 return(true); }
/// <summary> /// 尝试将结果转换成目标类型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="result"></param> /// <returns></returns> private T TryConvertType <T>(object result) { // 取第一项 object value; if (result is IList <object> rs) { value = rs.FirstOrDefault(); } else { value = result; } // 转换字符串 if (value is string str) { try { switch (str) { case "OK": return((T)Commands.Ok); case "PONG": return((T)Commands.Ok); } return(TypeConvert.C2Type <T>(str)); } catch (Exception e) { throw new RedisClientException($"将字符串({value})转为类型({typeof(T).Name})失败({e.Message})", MethodBase.GetCurrentMethod()); } } // 转换字节 if (value is byte[] byts) { try { object retVal; TypeCode typeCode = Type.GetTypeCode(typeof(T)); switch (typeCode) { case TypeCode.Object: retVal = ObjectConvert.C2Obj <T>(byts); break; case TypeCode.String: retVal = ObjectConvert.C2Str(byts); break; case TypeCode.DateTime: retVal = ObjectConvert.C2Date(byts); break; case TypeCode.Decimal: retVal = ObjectConvert.C2Dec(byts); break; case TypeCode.Double: retVal = ObjectConvert.C2Dbl(byts); break; case TypeCode.Single: retVal = ObjectConvert.C2Flt(byts); break; case TypeCode.Int64: retVal = ObjectConvert.C2Lng(byts); break; case TypeCode.Int32: retVal = ObjectConvert.C2Int(byts); break; case TypeCode.Int16: retVal = ObjectConvert.C2Short(byts); break; case TypeCode.UInt64: retVal = ObjectConvert.C2Lng(byts); break; case TypeCode.UInt32: retVal = ObjectConvert.C2Int(byts); break; case TypeCode.UInt16: retVal = ObjectConvert.C2Short(byts); break; case TypeCode.Byte: retVal = ObjectConvert.C2Byte(byts); break; case TypeCode.SByte: retVal = ObjectConvert.C2SByte(byts); break; case TypeCode.Char: retVal = ObjectConvert.C2Chr(byts); break; case TypeCode.Boolean: retVal = ObjectConvert.C2Bool(byts); break; default: retVal = TypeConvert.C2Type <T>(byts); break; } return((T)retVal); } catch (Exception e) { throw new RedisClientException($"将结果转换成类型({typeof(T).Name})失败({e.Message})", MethodBase.GetCurrentMethod()); } } return(default);