I'm trying to create a Redis provider for Strathweb.CacheOutput.WebApi2, but trying to convert from a byte[] -> RedisValue -> byte[] is returning null.
I can manually set the object type as byte[] instead of var / RedisValue and it will correctly return the value as a byte[], but after it has been set as a RedisValue its failing to convert it to a byte[].
His Interface has the Get always return an object so I can't force the type or use a separate call without having to modify the interface.
If I try to do an result as byte[]
I get
Cannot convert type 'StackExchange.Redis.RedisValue' to 'byte[]' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion
If I try to do a (byte[])result
I get Cannot cast 'result' (which has an actual type of 'StackExchange.Redis.RedisValue') to 'byte[]'
Is there something I'm missing or am I going to have to hack it in somehow by checking what type of data its looking for based on the key?
Here is the interface:
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; }
}
}
And here is how its called:
var val = _webApiCache.Get(cachekey) as byte[];
if (val == null) return;
Edit: Adding examples of the API I implemented using both ServiceStack.Redis v3 (working atm as it just uses object
and StackExchange.Redis which is not working)
https://github.com/mackayj/WebApi.OutputCache.Redis.ServiceStack
https://github.com/mackayj/WebApi.OutputCache.Redis.StackExchange
The following code using StackExchange.Redis can set/get value of generic type and convert RedisValue to byte[] in process, it should work fine for any serializable type.
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;
}
}
That's an interesting problem. There are a few ways I can think of approaching it:
byte[]
before storing itdynamic
Essentially, custom conversion operators don't work when unboxing, unless you use dynamic
I could also perhaps implement IConvertible
or some other well-known interface.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With