首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过RedisMessage反序列化BookSleeve的正确方法是什么?

通过RedisMessage反序列化BookSleeve的正确方法是什么?
EN

Stack Overflow用户
提问于 2013-02-20 19:38:21
回答 2查看 1.1K关注 0票数 0

我创建了以下单例类来处理Redis连接,并公开BookSleeve功能:

代码语言:javascript
复制
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中。

这是我的测试方法:

代码语言:javascript
复制
    [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()方法,所以我创建了一个静态助手类:

代码语言:javascript
复制
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;
        }
    }


}

不幸的是,这没有正确地将字符串反序列化回原来的形式,我得到的是这样的内容:⁡異汢獩敨⁤慶畬㩥ㄠ,而不是实际的原始文本。

有什么建议吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-02-21 15:02:58

RedisMessage表示即将发送到服务器的挂起请求;其中有几个具体实现,通常与要发送的参数的性质和数量有关。“反序列化”(甚至“序列化”) RedisMessage没有任何意义--这不是他们的目的。唯一明智的做法是将它们Write(...)Stream

如果您想要有关RedisMessage的信息,那么.ToString()有一个概述,但这不是一个可往返的,坦率地说是用于调试的。

RedisMessage是一个internal类;一个实现细节。除非您正在处理对核心代码的拉请求,否则永远不需要与RedisMessage交互。

在类似的级别上,有RedisResult,它表示从服务器返回的响应。如果您想要一种快速获取数据的方法,幸运的是,这要简单得多:

代码语言:javascript
复制
object val = result.Parse(true);

( true的意思是“进行推测性测试,看看数据是否像string")。但同样,这是一个不应该使用的internal实现细节。

票数 0
EN

Stack Overflow用户

发布于 2013-02-20 21:06:28

显然,这是一个编码类型问题,同时,稍微看一下此链接,我只添加了UTF8的编码类型,输出看起来很好:

代码语言:javascript
复制
   #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);

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14988473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档