0

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?

stuartd
  • 70,509
  • 14
  • 132
  • 163
Avinash
  • 79
  • 1
  • 7

1 Answers1

1

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?

stuartd
  • 70,509
  • 14
  • 132
  • 163
  • Your answer works for me..but can you suggest to me if I want to use generic types to class itself instead of methods – Avinash Aug 13 '20 at 07:58
  • But why? The cache doesn't care what key or value type you use. the cache _methods_ knows about keys and values, but the cache itself doesn't. If you have a use case where it does need to, let me know? – stuartd Aug 13 '20 at 22:23
  • This is what our own cache class looks like - no type constraints on the cache itself. Never been an issue. https://i.stack.imgur.com/e954R.png – stuartd Aug 13 '20 at 22:26
  • that's true Stuartd...just want to know how to do dependency injection if I faced the above scenario.Thanks for the quick response – Avinash Aug 14 '20 at 08:31
  • Is this what you're after? [Registering Open Generics in ASPNET Core Dependency Injection](https://ardalis.com/registering-open-generics-in-aspnet-core-dependency-injection) – stuartd Aug 14 '20 at 22:02