Reputation: 750
I'm trying to use Azure Redis Cache in .NET Core application. I have written a CacheHelper generic method which implements generic interface like below.
However this issue is more related to Generics.
I'm getting error while casting cache value to generic type. Is this the correct way to do? or Am i missing something? Please see the code below.
public class CacheHelper<T> : ICacheHelper<T>
{
private ICacheProvider _cacheProvider;
public CacheHelper(ICacheProvider cacheProvider)
{
_cacheProvider = cacheProvider;
}
public async Task<CacheResponse<T>> GetCacheValueAsync(string key)
{
RedisValue value = await _cacheProvider.GetCacheDatabase().StringGetAsync(key);
if (typeof(T).Equals(typeof(string)))
{
return value.HasValue
? new CacheResponse<T>(value) //I'm getting error here cannot cast type RedisValue to type T
: CacheResponse<T>.NoValue();
}
else
{
T obj = JsonConvert.DeserializeObject<T>(value);
return value.HasValue
? new CacheResponse<T>(obj)
: CacheResponse<T>.NoValue();
}
}
}
Upvotes: 4
Views: 1811
Reputation: 61
I would like to share one more implementation of converting RedisValue to 'T' type. RedisValue implements IConvertible interface and this interface has methods to convert the instance value to a common language runtime type. This might be helpful to someone.
private RedisValue GetStringInRedis(string key)
{
var redisDb = RedisConnection.GetDatabase();
var redisValue = redisDb.StringGet(redisKey);
if (redisValue.HasValue)
{
return redisValue;
}
return RedisValue.Null;
}
private T ChangeToType<T>(string key, RedisValue redisValue)
{
if (redisValue.IsNull)
return default(T);
try
{
var sRedisValue = redisValue;
if (typeof(T) == typeof(bool))
{
var tempRedisValue = (string) redisValue;
if (tempRedisValue.ToLower() == "true")
sRedisValue = RedisValue.Unbox(1);
else
sRedisValue = RedisValue.Unbox(0);
}
var obj = Convert.ChangeType(sRedisValue, typeof(T));
return (T) obj;
}
catch
{
throw new Exception($"Redis key '{key}' has invalid redis value '{redisValue}'");
}
}
public T GetValue<T>(string key)
{
var redisValue = GetStringInRedis(key);
return ChangeToType<T>(key, redisValue);
}
Upvotes: 0
Reputation: 39072
You could use the built-in Convert
class to your advantage here:
new CacheResponse<T>((T)Convert.ChangeType(value, typeof(T));
Upvotes: 3
Reputation: 3924
It seems to me you should create two different implementations if ICacheHelper<T>
interface.
One for the string
type that implements ICacheHelper<string>
.
One for all other types that implements ICacheHelper<T>
.
Upvotes: -1