StackExchange.Redis通过“as byte []”将RedisValue强制转换为byte [],返回null

时间:2014-10-03 17:23:47

标签: c# stackexchange.redis

我正在尝试为Strathweb.CacheOutput.WebApi2创建一个Redis提供程序,但是尝试从byte [] - >转换RedisValue - > byte []返回null。

我可以手动将对象类型设置为byte []而不是var / RedisValue,它会正确地将值作为byte []返回,但在将其设置为RedisValue后,它无法将其转换为字节[ ]

他的接口让Get总是返回一个对象,所以我不能强制该类型或使用单独的调用而不必修改接口。

如果我尝试result as byte[],我会得到 Cannot convert type 'StackExchange.Redis.RedisValue' to 'byte[]' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion

如果我尝试(byte[])result,我会Cannot cast 'result' (which has an actual type of 'StackExchange.Redis.RedisValue') to 'byte[]'

是否有我遗漏的东西,或者我不得不通过检查基于密钥查找的数据类型来以某种方式破解它?

这是界面:

namespace WebApi.OutputCache.Core.Cache
{
    public interface IApiOutputCache
    {
        void RemoveStartsWith(string key);
        T Get<T>(string key) where T : class;
        object Get(string key);
        void Remove(string key);
        bool Contains(string key);
        void Add(string key, object o, DateTimeOffset expiration, string dependsOnKey = null);
        IEnumerable<string> AllKeys { get; }
    }
}

以下是它的名称:

        var val = _webApiCache.Get(cachekey) as byte[];
        if (val == null) return;

编辑:添加我使用ServiceStack.Redis v3实现的API示例(因为它只使用object而工作atm而不使用的是StackExchange.Redis)

https://github.com/mackayj/WebApi.OutputCache.Redis.ServiceStack

https://github.com/mackayj/WebApi.OutputCache.Redis.StackExchange

3 个答案:

答案 0 :(得分:4)

byte[]RedisValue之间的转换使用conversion operator。但是,只有编译器将该值称为object,因此它不知道它需要调用转换运算符。即如果您编写以下代码:

object result = someRedisValue;
byte[] bytes = (byte[])result;

编译器为最后一行写了类似下面的内容,但失败了:

cast result to byte[] // runtime error: it's not a byte[]!
store that in 'bytes'

您可以在尝试转换对象之前让编译器知道对象的 real 类型来解决此问题。

byte[] bytes = (RedisValue)result;

这会导致编译器编写如下代码:

cast result to RedisValue
call RedisValue's implicit RedisValue to byte[] conversion on that
store that in 'bytes'

答案 1 :(得分:3)

这是一个有趣的问题。我可以通过几种方式来解决它:

  • 在存储之前将其投放到byte[]
  • dynamic
  • 作弊
  • 在存储之前将其包装在其他可识别的包装中

基本上,自定义转换运算符在取消装箱时不起作用,除非您使用dynamic

我也可以实现IConvertible或其他一些众所周知的界面。

答案 2 :(得分:2)

使用StackExchange.Redis的以下代码可以设置/获取泛型类型的值,并在过程中将RedisValue转换为byte [],它应该适用于任何可序列化类型。

    public static void SetItem<T>(string key, T value)
    {

        IDatabase redDb = GetDB();
        redDb.StringSet(key, ToByteArray<T>(value));
    }

    public static T GetItem<T>(string key)
    {
        IDatabase redDb = GetDB();
        RedisValue redisResult = redDb.StringGet(key);
        T objResult = FromByteArray<T>(redisResult);
        return objResult;
    }

   public static byte[] ToByteArray<T>(T obj)
   {
        if (obj == null)
            return null;
        BinaryFormatter bf = new BinaryFormatter();
        using (MemoryStream ms = new MemoryStream())
        {
            bf.Serialize(ms, obj);
            return ms.ToArray();
        }
    }

    public static T FromByteArray<T>(byte[] data)
    {
        if (data == null)
            return default(T);
        BinaryFormatter bf = new BinaryFormatter();
        using (MemoryStream ms = new MemoryStream(data))
        {
            object obj = bf.Deserialize(ms);
            return (T)obj;
        }
    }