ASP.NET Core 2 - Несколько сервисов кэширования красных лазурных изображений DI

В ASP.NET Core 2 мы можем добавить кэш Azure Redis так:

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

Тогда использование будет выглядеть так:

private readonly IDistributedCache _cache;

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

Как я могу это сделать, чтобы у меня было:

private readonly IDistributedCache _cache1;
private readonly IDistributedCache _cache2;

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

Мои вопросы, как я могу добавить еще одну службу, которая указывает на другое соединение кэша Azure Redis и экземпляр и разделить их, когда я хочу их использовать?

Ответ 1

За сценой, метод AddDistributedRedisCache() extension делает следующее (code on github):

  • Регистрирует действие для настройки RedisCacheOptions. За это отвечает Lambda, на которую вы переходите на AddDistributedRedisCache(). Экземпляр RedisCacheOptions передается конструктору RedisCache, завернутому в IOptions<T>.
  • Регистрирует реализацию Singletone RedisCache интерфейса IDistributedCache.

К сожалению, оба эти действия не очень подходят для того, что вы просите. Только одно действие может быть зарегистрировано для настройки определенного типа параметров. Встроенная реализация инжекции ядра .net не поддерживает регистрацию.

Есть еще решение, которое будет делать то, что вы хотите. Однако это решение несколько меня убило.

Фокус в том, что вы наследуете свой собственный RedisCacheOptions1, RedisCacheOptions2 от RedisCacheOptions и регистрируете различные конфигурации для них обоих.

Затем вы определяете свои настраиваемые интерфейсы IDistributedCache1 и IDistributedCache2, которые наследуются от IDistributedCache.

И, наконец, вы определяете классы RedisCache1 (который наследует реализацию от RedisCache, а также реализует IDistributedCache1) и RedisCache2 (то же самое).

Что-то вроде этого:

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>());