Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registration required on child container for proper disposal #62

Open
tonysneed opened this issue Sep 12, 2014 · 12 comments
Open

Registration required on child container for proper disposal #62

tonysneed opened this issue Sep 12, 2014 · 12 comments

Comments

@tonysneed
Copy link

If services are registered on a parent container, calling Dispose on a child container will not call dispose on registered services. Services must be registered directly on each child container. This is not easy to do with a Web API dependency resolver, where you would create a child container on BeginScope. The only workaround I have found is to call AutoRegister on the child container, but this is not ideal.

It seems like calling Dispose on a child container should Dispose dependencies that were registered on the parent container if they were not also registered on the child container?

@kentcb
Copy link

kentcb commented Oct 8, 2014

You describe the opposite behavior to what I would expect (i.e. the current behavior). The parent container would typically outlive the child, so disposing the parent when you dispose the child would mean the parent can't have any more children. Writing that makes me want to go and hug my kids...

The real question here is why you feel you need to register the services in the child container? If the services in question should be available to all children, why not just register them in the parent and let the bubbling behavior of resolutions find those services when you resolve against the child container?

@jonie
Copy link

jonie commented Nov 14, 2014

Ok, @kentcb is this expected behavior (see code)?

using System;
using TinyIoC;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var parent = TinyIoCContainer.Current;
            parent.Register<IFoo, Disposable>().AsMultiInstance();

            var child = parent.GetChildContainer();
            var instance = child.Resolve<IFoo>();

            instance.Some();
            child.Dispose();

            Console.WriteLine("Child container was disposed, but resolved via child container instance not?");
            Console.ReadLine();
        }
    }

    interface IFoo {
        void Some();
    }

    class Disposable : IDisposable, IFoo
    {
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool b)
        {
            Console.WriteLine("Disposed!");
        }

        ~Disposable()
        {
            Dispose(false);
        }

        public void Some()
        {
            Console.WriteLine("...work...");
        }
    }
}

@kentcb
Copy link

kentcb commented Nov 15, 2014

@jonie: to be clear, I can't answer for the author of TinyIoC - these are just my thoughts.

Your example still seems to have the correct behavior to me. By registering IFoo on the parent container, you're tying the lifetime of any IFoos to the parent container. If you want the IFoo's lifetime to be tied to the child container, why wouldn't you register it there?

@tonysneed
Copy link
Author

The real question I have is how to write a dependency resolver for Web API using TinyIoC, in which the scope is disposed at the conclusion of each request. Does TinyIoC have the notion of scope?

@MihaMarkic
Copy link

Has this ever been solved? @tonysneed raised a valid point and @jonie provided a valid example of how it should be. If that's not what it should be, then either we misunderstood the purpose if child container or there is another way to deal with limited lifetimes.

@niemyjski
Copy link
Collaborator

I don't think so, but I haven't dived in... Would you mind taking a look? I'd agree with @kentcb's last comment.

@MihaMarkic
Copy link

@niemyjski Here is an example. I would register all stuff globally, at application start. And at some point I'd like to have a limited lifespan. Doing it your way, I'd have to create child container and register everything again (or at least what I need) even though it is already registered.
Why not create a child container, use it and then dispose it to clear whatever was created?
What purpose has child container otherwise? To override few registrations?

@niemyjski
Copy link
Collaborator

That makes sense and is straight forward. My concern though, is if you have a parent and child containers and you have a parent object like IFoo and you dispose of the child container. Then dispose should be called on all objects in the child container. So now you have a disposed object registered in the parent which might be a singleton.

@MihaMarkic
Copy link

@niemyjski Singletons shouldn't be disposed by child container IMO.

@niemyjski
Copy link
Collaborator

niemyjski commented Oct 24, 2019 via email

@MihaMarkic
Copy link

@niemyjski You mean "singletons that are resolved and created (because they don't exist on parent container) on child container"? That's an option as well. Either that or transfer ownership to parent-most container. I would assume the later, but both should work.

@niemyjski
Copy link
Collaborator

Seems weird that parent and child containers could have different scopes but share the same instance. It's almost like if anything is registered in the child container we dispose of it, otherwise get it from the parent container instance. I'm just trying to think of what's straight forward, but I'm all in for what the general consensus is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants