Pytanie ASP.NET Core 2 - wiele usług pamięci podręcznej Redis Azure DI


W środowisku ASP.NET Core 2 możemy dodać pamięć podręczną Redis Azure w następujący sposób:

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

Następnie użycie będzie wyglądało następująco:

private readonly IDistributedCache _cache;

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

Jak mogę to zrobić, aby uzyskać:

private readonly IDistributedCache _cache1;
private readonly IDistributedCache _cache2;

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

Na moje pytania w jaki sposób mogę dodać inną usługę, która wskazuje na inne połączenie Azure Redis Cache i instancję i czy rozdziela je, gdy chcę z nich korzystać?


14
2017-10-18 11:21


pochodzenie


Takich zaawansowanych scenariuszy nie da się tak naprawdę zarządzać z domyślnymi ustawieniami IDistributedCache podejście. Powinieneś używać biblioteki takiej jak CacheManager co pozwala na definiowanie różnych pamięci podręcznych na podstawie argumentów typu. - Federico Dipuma
Potencjalną opcją jest użycie a Wzór strategii aby wybrać pamięć podręczną do użycia w czasie wykonywania. - NightOwl888


Odpowiedzi:


Za kulisami, AddDistributedRedisCache() metoda rozszerzenia wykonuje następujące czynności (kod na github):

  1. Rejestruje akcję do skonfigurowania RedisCacheOptions. Lambda, którą przechodzisz AddDistributedRedisCache() jest za to odpowiedzialny. Wystąpienie RedisCacheOptions jest przekazywane do konstruktora RedisCache owinięte w IOptions<T>.
  2. Rejestruje implementację Singletone RedisCache z IDistributedCache berło.

Niestety, oba te działania nie pasują do tego, o co prosisz. Dla skonfigurowania określonego typu opcji można zarejestrować tylko jedną czynność. Natywna implementacja wtrysku zależności rdzeniowej .net nie wspiera nadpisanie rejestracji.

Nadal istnieje rozwiązanie, które zrobi to, co chcesz. Jednak to rozwiązanie nieco mnie zabija.

Sztuczka polega na tym, że dziedziczysz niestandardowe RedisCacheOptions1, RedisCacheOptions2 z RedisCacheOptions i rejestrujesz odrębne konfiguracje dla nich obu.

Następnie definiujesz własne interfejsy IDistributedCache1 i IDistributedCache2, które dziedziczą po IDistributedCache.

I na koniec definiujesz klasy RedisCache1 (dziedziczy implementację z RedisCache, a także implementuje IDistributedCache1) i RedisCache2 (to samo).

Coś takiego:

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

11
2017-11-11 16:02



Byłem na tej samej ścieżce co ty. Co masz na myśli poprzez: however this solution somewhat killing me? Nie widzę niczego złego w tym podejściu i myślę, że będzie działało dobrze - user2818430
Chodzi mi o to, że wymaga to znacznie więcej wysiłku niż powinno :( - CodeFuller