Open tonysneed opened 10 years ago
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?
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...");
}
}
}
@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 IFoo
s 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?
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?
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.
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.
@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?
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.
@niemyjski Singletons shouldn't be disposed by child container IMO.
If you dispose the child container than dispose should be called on the singletons registered in the child container..
@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.
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.
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?