2014-10-03 15 views
5

Tôi đang cố gắng tạo nhà cung cấp Redis cho Strathweb.CacheOutput.WebApi2, nhưng cố chuyển đổi từ byte [] -> RedisValue - > byte [] trả về null.StackExchange.Redis truyền RedisValue thành byte [] qua "dưới dạng byte []" trả về giá trị rỗng

Tôi có thể đặt loại đối tượng thành byte [] thay vì var/RedisValue và nó sẽ trả về giá trị dưới dạng byte [], nhưng sau khi nó được đặt thành RedisValue, nó sẽ không chuyển đổi thành byte [].

Giao diện của anh ấy luôn Nhận được đối tượng để tôi không thể ép buộc loại hoặc sử dụng cuộc gọi riêng mà không phải sửa đổi giao diện.

Nếu tôi cố gắng làm một result as byte[] tôi nhận được Cannot convert type 'StackExchange.Redis.RedisValue' to 'byte[]' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion

Nếu tôi cố gắng làm một (byte[])result tôi nhận được Cannot cast 'result' (which has an actual type of 'StackExchange.Redis.RedisValue') to 'byte[]'

Có cái gì tôi đang thiếu hoặc tôi sẽ phải hack nó trong bằng cách nào đó bằng cách kiểm tra loại dữ liệu tìm kiếm dựa trên khóa nào?

Dưới đây là giao diện:

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; } 
    } 
} 

Và đây là cách nó được gọi là:

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

Chỉnh sửa: Thêm ví dụ về các API tôi thực hiện sử dụng cả hai ServiceStack.Redis v3 (làm việc atm vì nó chỉ sử dụng object và StackExchange.Redis không hoạt động)

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

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

Trả lời

3

Việc chuyển đổi giữa byte[]RedisValue sử dụng một conversion operator. Tuy nhiên, giá trị này chỉ được biết đến với trình biên dịch là object, do đó, nó không biết rằng nó cần phải gọi toán tử chuyển đổi. I E. nếu bạn viết đoạn mã sau:

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

Trình biên dịch viết một cái gì đó như sau cho dòng cuối cùng, mà thất bại:

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

Bạn có thể giải quyết việc này bằng cách cho phép trình biên dịch biết thực loại của đối tượng trước khi bạn cố chuyển đổi nó.

byte[] bytes = (RedisValue)result; 

Điều này làm cho trình biên dịch để viết mã như thế này:

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

Vấn đề là giao diện trả về một đối tượng và mã gọi đang thực hiện lệnh 'as byte []'. Tôi đang cố gắng để không sửa đổi hoặc giao diện hoặc mã chính cho nó nhưng tôi nghĩ rằng tôi chỉ sẽ thêm một phương pháp mới mà trả về byte [] cho bây giờ. Tôi đã chỉnh sửa bài viết của mình để hiển thị mã gọi đúng với 'as byte []' – John

2

Đó là một vấn đề thú vị.Có một vài cách tôi có thể nghĩ ra cách tiếp cận nó:

  • cast nó vào một byte[] trước khi lưu trữ nó
  • cheat với dynamic
  • bọc nó trong một số wrapper mang tính chất khác trước khi lưu trữ nó

Về cơ bản, toán tử chuyển đổi tùy chỉnh không hoạt động khi bỏ hộp trừ khi bạn sử dụng dynamic

Tôi cũng có thể thực hiện ment IConvertible hoặc một số giao diện nổi tiếng khác.

+0

Càng nghĩ về nó, tôi càng chắc chắn rằng 'RedisValue' nên': IConvertible'. Điều đó có thể sẽ nằm trong đợt giảm tiếp theo. –

+0

Cảm ơn bạn đã trả lời nhanh chóng Marc! Tôi đã thay thế mã đó bằng một cuộc gọi trực tiếp trả về byte [] thay vì đối tượng và nhận thấy nó thực sự thất bại ở nhiều vị trí khác (ví dụ như 'string' và' as MediaTypeHeaderValue'). Tôi đã thử chỉ cần thiết lập nó như là một 'kết quả năng động = _database.GetString (key)' nhưng đó đã cho kết quả tương tự, những gì bạn đã có nghĩa là gian lận nó với năng động? Có cách nào để chỉ trả lại một đối tượng thay vì chuyển đổi nó sang RedisValue không? – John

+0

Tôi đã kết thúc chỉ cần chuyển ra 'StackExchange.Redis' cho' ServiceStack.Redis' và tôi đã có thể làm điều đó mà không có vấn đề. Tôi thực sự thích phiên bản của bạn tốt hơn vì nó nhỏ hơn nhiều. Nếu có một cách để chỉ sử dụng 'đối tượng' không phải' RedisValue' làm kiểu trả về, hãy cho tôi biết để tôi có thể đổi nó trở lại :) – John

1

Đoạn mã sau bằng cách sử dụng StackExchange.Redis có thể đặt/nhận giá trị của loại chung và chuyển RedisValue thành byte [] trong quá trình, nó sẽ hoạt động tốt đối với mọi loại có thể tuần tự hóa.

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; 
     } 
    } 
Các vấn đề liên quan