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

Joh*_*ohn 6 c# stackexchange.redis

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

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

他的接口有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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是它的名称:

        var val = _webApiCache.Get(cachekey) as byte[];
        if (val == null) return;
Run Code Online (Sandbox Code Playgroud)

编辑:添加我使用ServiceStack.Redis v3实现的API示例(因为刚刚使用atm object而工作,而不能正常工作的StackExchange.Redis)

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

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

Mar*_*ell 5

这是一个有趣的问题。我可以想到以下几种方法来解决这个问题:

  • byte[]在存储之前将其转换为 a
  • 欺骗与dynamic
  • 在存储之前将其包装在其他可识别的包装中

本质上,自定义转换运算符在拆箱时不起作用,除非您使用dynamic

我也许还可以实现IConvertible或其他一些众所周知的接口。


Bas*_*nic 5

使用 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)


Tim*_* S. 4

之间的转换byte[]RedisValue使用转换操作符.但是,该值仅为编译器所知object,因此它不知道它需要调用转换运算符.即如果您编写以下代码:

object result = someRedisValue;
byte[] bytes = (byte[])result;
Run Code Online (Sandbox Code Playgroud)

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

cast result to byte[] // runtime error: it's not a byte[]!
store that in 'bytes'
Run Code Online (Sandbox Code Playgroud)

您可以通过在尝试转换对象之前让编译器知道对象的实际类型来解决此问题.

byte[] bytes = (RedisValue)result;
Run Code Online (Sandbox Code Playgroud)

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

cast result to RedisValue
call RedisValue's implicit RedisValue to byte[] conversion on that
store that in 'bytes'
Run Code Online (Sandbox Code Playgroud)