0

For regular case how to manage disposables such post as How to correctly and safely dispose of singletons instances registered in the container when an ASP.NET Core app shuts down explains how to do it.

But I have a slightly different case -- I don't have single instance of some worker IFoo like here:

interface IFoo : IDisposable // not my case

which you know how to dispose, just call Dispose on an instance of IFoo.

No, my IFoo is not IDisposable:

interface IFoo // my case

instead of single instance, I have a pair of instances on creation -- (IFoo,IDisposable). When I have to do real work, I use the first item, because there is all logic there, when I am done, I call Dispose on the second item.

You could say it is decoupling put at extreme.

And when I am at ASP.NET Core I have problem with DI -- I have a pair like above, I can register IFoo with for example services.AddScoped, but how to tell services that there is distinct/separate IDisposable at hand which should be disposed when the work is done and the scope is gone?

astrowalker
  • 3,123
  • 3
  • 21
  • 40
  • What do you mean you have a pair of instances? Do you mean a pair of *references* to the same instance? – madreflection Feb 25 '20 at 08:04
  • @madreflection, ok, pair of references to two distinct instances. For simplicity let's say you have some method `Create` which signature is like this `(IFoo,IDisposable) Create()`, so as the effect you can do work (with first item) and when you are done you call `Dispose` on the second item. – astrowalker Feb 25 '20 at 08:28
  • Funny, if that was going to be your response, I was going to suggest exactly what ahydrax just posted in his answer. Try that! – madreflection Feb 25 '20 at 08:29
  • Although, I should point out that having a reference to just `IDisposable`, especially if that's being injected as such, doesn't make a lot of sense. What are you registering as the concrete class for `IDisposable`? – madreflection Feb 25 '20 at 08:32
  • @madreflection, there is of course some concrete type, but it is hidden. At hand I have only interfaces, and they are always split, i.e. if there is `IDisposable` involved it is a separate item and the "main" interface never inherits from `IDisposable`. – astrowalker Feb 25 '20 at 08:48
  • 1
    If it's just that the the concrete class implements `IFoo` and `IDisposable` without the former inheriting the latter, the container will still take care of disposing it without having to inject a reference to its `IDisposable`. – madreflection Feb 25 '20 at 08:50
  • @madreflection, thank you, this is good to know. However I cannot firmly rely on it -- (a) it is per case knowledge (b) to be sure I would have to check it out by reflection. So, the info you wrote is valuable for me, but in such cases I won't dare to use it :-). – astrowalker Feb 25 '20 at 09:30

1 Answers1

3

You could create a wrapper around (IFoo, IDisposable), let's say:

public class DisposableFoo : IDisposable
{
    // Assume FooConcrete implements IFoo and IDisposable
    private readonly FooConcrete _foo;

    public DisposableFoo(FooConcrete fooConcrete) { _foo = fooConcrete; }

    public IFoo Instance => _foo;

    public void Dispose() => _foo.Dispose();
}

And then in Startup.cs you could do the following to keep your abstractions clean:

services.AddTransient<FooConcrete>();
services.AddScoped<DisposableFoo>();
services.AddScoped<IFoo>(ctx => ctx.Resolve<DisposableFoo>.Instance); 

In this case the underlying FooConrecte will be disposed at the end of scope lifetime properly.

ahydrax
  • 73
  • 1
  • 6
  • There is no `FooConcrete` but it is still doable, in my case wrapper would have to take the pair and integrate those two. Thank you! – astrowalker Feb 25 '20 at 08:31