Search code examples
c#asp.net-corecaching.net-coreazure-redis-cache

How to use dependency injection for key value pair class to use Redis Cache


Here is my code:

public class RedisCache<TKey, TVal> : ICache<TKey, TVal> where TVal : class
{
        TimeSpan _defaultCacheDuration;
        Lazy<ConnectionMultiplexer> _connection;

        public RedisCache(string connectionString, TimeSpan defaultDuration)
        {
            if (defaultDuration <= TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(defaultDuration), "Duration must be greater than zero");

            _connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(connectionString));

            _defaultCacheDuration = defaultDuration;
        }

        public async Task<TVal> GetAsync(TKey key)
        {
            var database = _connection.Value.GetDatabase();
            string keyString = key?.ToString() ?? "null";
            var result = await database.StringGetAsync(keyString);
            return result.IsNull ? null : GetObjectFromString(result);
        }
}

How to inject this in startup.cs?

I tried this which throws compile-time error:
services.AddSingleton<ICache<>>(provider => new RedisCache<,>("myPrettyLocalhost:6379", new TimeSpan(1)));

Could someone help me with this?


Solution

  • In the code you've posted, you've added your type definitions to the cache, but in fact you only use them in the method, so your class should look like this:

    public class RedisCache {
        TimeSpan _defaultCacheDuration;
        Lazy<ConnectionMultiplexer> _connection;
    
        public RedisCache(string connectionString, TimeSpan defaultDuration) {
            if (defaultDuration <= TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(defaultDuration), "Duration must be greater than zero");
    
            _connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(connectionString));
    
            _defaultCacheDuration = defaultDuration;
        }
    
        public async Task<TVal> GetAsync<TKey, TVal>(TKey key) where TVal : class {
            var database = _connection.Value.GetDatabase();
            string keyString = key?.ToString() ?? "null";
            var result = await database.StringGetAsync(keyString);
            return result.IsNull ? null : GetObjectFromString(result);
        }
    }
    

    Which makes injection simple:

    services.AddSingleton<ICache>(provider => new RedisCache("myPrettyLocalhost:6379", new TimeSpan(1)));
    

    If there's a specific reason why you added the key and value types to the class, can you edit your question to show the reason?