我创建了以下单例类来处理Redis连接,并公开BookSleeve功能:
public class RedisConnection
{
private static RedisConnection _instance = null;
private BookSleeve.RedisSubscriberConnection _channel;
private readonly int _db;
private readonly string[] _keys; // represent channel name
public BookSleeve.RedisConnection _connection;
/// <summary>
/// Initialize all class parameters
/// </summary>
private RedisConnection(string serverList, int db, IEnumerable<string> keys)
{
_connection = ConnectionUtils.Connect(serverList);
_db = db;
_keys = keys.ToArray();
_connection.Closed += OnConnectionClosed;
_connection.Error += OnConnectionError;
// Create a subscription channel in redis
_channel = _connection.GetOpenSubscriberChannel();
// Subscribe to the registered connections
_channel.Subscribe(_keys, OnMessage);
// Dirty hack but it seems like subscribe returns before the actual
// subscription is properly setup in some cases
while (_channel.SubscriptionCount == 0)
{
Thread.Sleep(500);
}
}
/// <summary>
/// Do something when a message is received
/// </summary>
/// <param name="key"></param>
/// <param name="data"></param>
private void OnMessage(string key, byte[] data)
{
// since we are just interested in pub/sub, no data persistence is active
// however, if the persistence flag is enabled, here is where we can save the data
// The key is the stream id (channel)
//var message = RedisMessage.Deserialize(data);
var message = Helpers.BytesToString(data);
if (true) ;
//_publishQueue.Enqueue(() => OnReceived(key, (ulong)message.Id, message.Messages));
}
public static RedisConnection GetInstance(string serverList, int db, IEnumerable<string> keys)
{
if (_instance == null)
{
// could include some sort of lock for thread safety
_instance = new RedisConnection(serverList, db, keys);
}
return _instance;
}
private static void OnConnectionClosed(object sender, EventArgs e)
{
// Should we auto reconnect?
if (true)
{
;
}
}
private static void OnConnectionError(object sender, BookSleeve.ErrorEventArgs e)
{
// How do we bubble errors?
if (true)
{
;
}
}
}在OnMessage()中,由于以下错误,var message = RedisMessage.Deserialize(data);被注释掉:
RedisMessage由于其保护级别而无法访问。
RedisMessage是BookSleeve中的一个抽象类,我有点不明白为什么我不能使用它。
我遇到这个问题是因为当我向一个通道(pub/sub)发送消息时,我可能想在OnMessage()中对它们做些什么--例如,如果设置了持久性标志,我可以选择开始记录数据。问题是此时数据是序列化的,我希望反序列化它(字符串),并将其保存在Redis中。
这是我的测试方法:
[TestMethod]
public void TestRedisConnection()
{
// setup parameters
string serverList = "dbcache1.local:6379";
int db = 0;
List<string> eventKeys = new List<string>();
eventKeys.Add("Testing.FaucetChannel");
BookSleeve.RedisConnection redisConnection = Faucet.Services.RedisConnection.GetInstance(serverList, db, eventKeys)._connection;
// broadcast to a channel
redisConnection.Publish("Testing.FaucetChannel", "a published value!!!");
}由于无法使用Deserialize()方法,所以我创建了一个静态助手类:
public static class Helpers
{
/// <summary>
/// Serializes a string to bytes
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
public static byte[] StringToBytes(string str)
{
try
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
catch (Exception ex)
{
/* handle exception omitted */
return null;
}
}
/// <summary>
/// Deserializes bytes to string
/// </summary>
/// <param name="bytes"></param>
/// <returns></returns>
public static string BytesToString(byte[] bytes)
{
string set;
try
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
catch (Exception ex)
{
// removed error handling logic!
return null;
}
}
}不幸的是,这没有正确地将字符串反序列化回原来的形式,我得到的是这样的内容:異汢獩敨慶畬㩥ㄠ,而不是实际的原始文本。
有什么建议吗?
发布于 2013-02-21 15:02:58
RedisMessage表示即将发送到服务器的挂起请求;其中有几个具体实现,通常与要发送的参数的性质和数量有关。“反序列化”(甚至“序列化”) RedisMessage没有任何意义--这不是他们的目的。唯一明智的做法是将它们Write(...)为Stream。
如果您想要有关RedisMessage的信息,那么.ToString()有一个概述,但这不是一个可往返的,坦率地说是用于调试的。
RedisMessage是一个internal类;一个实现细节。除非您正在处理对核心代码的拉请求,否则永远不需要与RedisMessage交互。
在类似的级别上,有RedisResult,它表示从服务器返回的响应。如果您想要一种快速获取数据的方法,幸运的是,这要简单得多:
object val = result.Parse(true);( true的意思是“进行推测性测试,看看数据是否像string")。但同样,这是一个不应该使用的internal实现细节。
发布于 2013-02-20 21:06:28
显然,这是一个编码类型问题,同时,稍微看一下此链接,我只添加了UTF8的编码类型,输出看起来很好:
#region EncodingType enum
/// <summary>
/// Encoding Types.
/// </summary>
public enum EncodingType
{
ASCII,
Unicode,
UTF7,
UTF8
}
#endregion
#region ByteArrayToString
/// <summary>
/// Converts a byte array to a string using Unicode encoding.
/// </summary>
/// <param name="bytes">Array of bytes to be converted.</param>
/// <returns>string</returns>
public static string ByteArrayToString(byte[] bytes)
{
return ByteArrayToString(bytes, EncodingType.Unicode);
}
/// <summary>
/// Converts a byte array to a string using specified encoding.
/// </summary>
/// <param name="bytes">Array of bytes to be converted.</param>
/// <param name="encodingType">EncodingType enum.</param>
/// <returns>string</returns>
public static string ByteArrayToString(byte[] bytes, EncodingType encodingType)
{
System.Text.Encoding encoding=null;
switch (encodingType)
{
case EncodingType.ASCII:
encoding=new System.Text.ASCIIEncoding();
break;
case EncodingType.Unicode:
encoding=new System.Text.UnicodeEncoding();
break;
case EncodingType.UTF7:
encoding=new System.Text.UTF7Encoding();
break;
case EncodingType.UTF8:
encoding=new System.Text.UTF8Encoding();
break;
}
return encoding.GetString(bytes);
}
#endregion--更新--
更简单:var message = Encoding.UTF8.GetString(data);
https://stackoverflow.com/questions/14988473
复制相似问题