Like the below code, I have to use the factory/func way of registration with container as I don't know the value of "userId" property ahead of time but only during runtime. This is working & no issues with functionality aspects.
container.AddSingleton<IBLogic, BLogic>(); //explicitly registration 'BLogic' service object
container.AddSingleton<Func<string, IDBCache>>
(p=> (userId) => new IDBCache(userId, p.GetService<IBLogic>()));
Since here I'm using "new IDBCache", as per the link framework does not dispose of the services automatically.
Questions:
To make framework to dispose of the services automatically, is there any way out?
container.AddSingleton<Func<string, IDBCache>> (p=> (userId) => new IDBCache(userId, p.GetService()));
Since I'm just registering the definition of func/factory not the service object(like 'BLogic') as such, does AddSingleton provides any advantage over using 'AddScoped' or 'AddTransisent' like below?
container.AddTransisent<Func<string, IDBCache>>
(p=> (userId) => new IDBCache(userId, p.GetService<IBLogic>()));
There's no easy fix for this. MS.DI doesn't contain a
RegisterForDisposalmethod that you can call. You will have to create a separate wrapper that implements disposable to which you can hook your created instances. For instance:Where the
DisposeWrapperlooks like this:Such implementation, however, comes with quite some caveats, because
DisposeWrappershould be registered using the same scope as you want to cache yourIDBCache. That's why in the example above, I registered bothDisposeWrapperand the factory asScoped.Registering
DisposeWrapperas Singleton, means that createdIDBCacheinstances will only get disposed when the application ends. If you create manyIDBCacheinstances during the lifetime of the application, it will cause a memory leak. This is unlikely a good idea in your scenario.Registering both as transient, on the other hand, could still (confusingly) cause memory leaks, because the factory could be injected into a singleton, causing it (and its
DisposeWrapper) to become a Captive Dependency.Because of the complications of this design, I recommend changing your design.
If you redesign
IDBCachein such way that runtime data isn't required during object construction, you can allowIDBCacheto be registered in the container without factory (e.g.AddTransient<IDBCache>()) which allows it to be disposed normally by the container. This will remove all above-introduced complexity.