19

In ASP.NET Core 2 we can add a Azure Redis Cache like this:

 services.AddDistributedRedisCache(config =>
 {
    config.Configuration = Configuration.GetConnectionString("RedisCacheConnection");
    config.InstanceName = "MYINSTANCE";
 });

Then the usage will be like this:

private readonly IDistributedCache _cache;

public MyController(IDistributedCache cache)
{
   _cache = cache;
}

How can I do it so that I will have:

private readonly IDistributedCache _cache1;
private readonly IDistributedCache _cache2;

public MyController(IDistributedCache cache1, IDistributedCache cache2)
{
   _cache1 = cache1;
   _cache2 = cache2;
}

My questions how can I add another service that points to a different Azure Redis Cache Connection and instance and make separation of them when I want to use them?

user2818430
  • 5,853
  • 21
  • 82
  • 148
  • Such advanced scenarios are not really manageable with the default `IDistributedCache` approach. You should use a library like [CacheManager](http://cachemanager.michaco.net/) which allows you to define different caches based on type arguments. – Federico Dipuma Oct 18 '17 at 11:45
  • 2
    A potential option is to use a [Strategy Pattern](https://stackoverflow.com/a/46597099) to select the cache to use at runtime. – NightOwl888 Oct 18 '17 at 17:17

1 Answers1

20

Behind the scene, AddDistributedRedisCache() extension method does the following (code on github):

  1. Registers action to configure RedisCacheOptions. Lambda that you pass to AddDistributedRedisCache() is responsible for that. Instance of RedisCacheOptions is passed to constructor of RedisCache wrapped into IOptions<T>.
  2. Registers Singletone implementation RedisCache of IDistributedCache interface.

Unfortunatelly, both of these actions aren't well suited for what you ask. Only one action could be registered for configuring specific type of options. Native implementation of .net core dependency injection does not support registration override.

There is still a solution that will do what you want. However this solution somewhat killing me.

The trick is that you inherit your custom RedisCacheOptions1, RedisCacheOptions2 from RedisCacheOptions and register distinct configurations for both of them.

Then you define your custom IDistributedCache1 and IDistributedCache2 interfaces that inherit from IDistributedCache.

And finally you define classes RedisCache1 (that inherits implementation from RedisCache and also implements IDistributedCache1) and RedisCache2 (the same).

Something like this:

public interface IDistributedCache1 : IDistributedCache
{
}

public interface IDistributedCache2 : IDistributedCache
{
}

public class RedisCacheOptions1 : RedisCacheOptions
{
}

public class RedisCacheOptions2 : RedisCacheOptions
{
}

public class RedisCache1 : RedisCache, IDistributedCache1
{
    public RedisCache1(IOptions<RedisCacheOptions1> optionsAccessor) : base(optionsAccessor)
    {
    }
}

public class RedisCache2 : RedisCache, IDistributedCache2
{
    public RedisCache2(IOptions<RedisCacheOptions2> optionsAccessor) : base(optionsAccessor)
    {
    }
}

public class MyController : Controller
{
    private readonly IDistributedCache _cache1;
    private readonly IDistributedCache _cache2;

    public MyController(IDistributedCache1 cache1, IDistributedCache2 cache2)
    {
        _cache1 = cache1;
        _cache2 = cache2;
    }
}

//  Bootstrapping

services.AddOptions();

services.Configure<RedisCacheOptions1>(config =>
{
    config.Configuration = Configuration.GetConnectionString("RedisCacheConnection1");
    config.InstanceName = "MYINSTANCE1";
});
services.Configure<RedisCacheOptions2>(config =>
{
    config.Configuration = Configuration.GetConnectionString("RedisCacheConnection2");
    config.InstanceName = "MYINSTANCE2";
});

services.Add(ServiceDescriptor.Singleton<IDistributedCache1, RedisCache1>());
services.Add(ServiceDescriptor.Singleton<IDistributedCache2, RedisCache2>());
CodeFuller
  • 30,317
  • 3
  • 63
  • 79
  • I was actually on the same path as you. What do you mean by: `however this solution somewhat killing me`? I don't see anything wrong with this approach and i think will work fine – user2818430 Nov 11 '17 at 16:48
  • 3
    I mean it requires much more efforts that it should :( – CodeFuller Nov 11 '17 at 17:27