We have a class in our .net6 WebAPI project used for two-level caching. We inject two instances of an ICacheClient
interface, one used for short-term caching and one used for long-term. One of the caches is configured as a singleton, but it is injecting a new instance for every request. The container is set up like so:
public static void RegisterDependencies(this IContainer container)
{
container.Register<StackExchangeRedisCacheClient>(Reuse.Singleton, Made.Of(() => new StackExchangeRedisCacheClient(Arg.Of<ISerializer>(), Arg.Of<IOptions<ConnectionStrings>>())));
container.Register<TwoLevelCacheClient>(Made.Of(() => new TwoLevelCacheClient(Arg.Of<MemoryCacheClient>(), Arg.Of<StackExchangeRedisCacheClient>())));
}
The TwoLevelCacheClient
just takes a two ICacheClient
parameters:
public class TwoLevelCacheClient : ITwoLevelCacheClient
{
public TwoLevelCacheClient(ICacheClient firstLevelCacheClient, ICacheClient secondLevelCacheClient)
{
...
}
}
Even though the StackExchangeRedisCacheClient
is set as a singleton, a new instance is injected into the TwoLevelCacheClient
for every request. The TwoLevelCacheClient
is configured as transient lifetime.
I wasn't sure if it was because the MadeOf
parameter is being used as a factory function, so I tried using reflection to specify the constructor instead, but it made no difference. The dryIoc docs indicate this function is never run
Note: The code
() => new Foo(Arg.Of<IDependency>()
is just a specification expression and won't be executed
https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/SelectConstructorOrFactoryMethod.cs
Edit: I have also tried registering a single client using that with a service key, but that also doesn't appear to work:
public static void RegisterDependencies(this IContainer container)
{
var redisCacheClient = new StackExchangeRedisCacheClient(container.Resolve<ISerializer>(), container.Resolve<IOptions<ConnectionStrings>>());
container.RegisterInstance(redisCacheClient, serviceKey: "redisCacheClient");
container.Register<StackExchangeRedisCacheClient>(Reuse.Singleton, Made.Of(() => new StackExchangeRedisCacheClient(Arg.Of<ISerializer>(), Arg.Of<IOptions<ConnectionStrings>>())));
container.Register<TwoLevelCacheClient>(Made.Of(() => new TwoLevelCacheClient(Arg.Of<MemoryCacheClient>(), Arg.Of<StackExchangeRedisCacheClient>("redisCacheClient"))));
}
The problem was in the line container.Register<TwoLevelCacheClient>(Made.Of(() => new TwoLevelCacheClient(Arg.Of<MemoryCacheClient>(), Arg.Of<StackExchangeRedisCacheClient>("redisCacheClient"))));
, however it was being injected as ITwoLevelCacheClient, so was ignoring the binding. D'oh