2014-10-03 291 views
5

我試圖爲一個字節[] - > RedisValue轉換爲Strathweb.CacheOutput.WebApi2創建一個Redis提供程序, > byte []返回null。StackExchange.Redis將RedisValue轉換爲byte []通過「as 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; 

編輯:API的實例添加我實現同時使用ServiceStack.Redis V3(因爲它ATM工作只是使用object和StackExchange.Redis不工作)

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

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

回答

3

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' 

你可以讓編譯器解決了這個認識真正類型嘗試對其進行轉換之前的對象。

byte[] bytes = (RedisValue)result; 

這將導致編譯器來寫這樣的代碼:

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

問題是接口正在返回一個對象,調用代碼正在做一個'as byte []'。我試圖不修改接口或主代碼,但我想我現在只是添加一個返回字節[]的新方法。我編輯我的帖子,顯示正確的調用代碼與'作爲字節[]' – John 2014-10-03 17:43:40

2

這是一個有趣的問題。還有我能想到接近它的幾種方法:

  • 其轉換爲byte[]存放
之前將其存儲
  • 作弊與dynamic
  • 敷在一些其他可識別包裝前

    本質上,自定義轉換運算符在拆箱時不起作用,除非您使用dynamic

    我也可以實現IConvertible或其他一些衆所周知的界面。

  • +0

    我越想到它,我更確定''RedisValue'應該':IConvertible'。這可能會在下一個下降。 – 2014-10-03 18:04:25

    +0

    感謝您的快速回復Marc!我用一個直接調用代替了那個代碼,它返回的是byte []而不是object,並且注意到它在多個其他地方('as string'和'MediaTypeHeaderValue'調用)實際上失敗了。我試着把它設置爲一個'dynamic result = _database.GetString(key)',但是它給出了相同的結果,你用動態作弊是什麼意思?有沒有辦法讓它返回一個對象,而不是將其轉換爲RedisValue? – John 2014-10-03 18:20:08

    +0

    我最終只是爲'ServiceStack.Redis'切換了'StackExchange.Redis',並且我能夠毫無問題地做到這一點。我非常喜歡你的版本,因爲它更小。如果有一種方法只是使用'object'而不是'RedisValue'作爲返回類型,請讓我知道,所以我可以將它交換回來:) – John 2014-10-03 19:32:13

    1

    下面的代碼使用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; 
         } 
        } 
    
    相關問題