-
Notifications
You must be signed in to change notification settings - Fork 458
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
Burdens are not Release Policy aware from TypedFactories for disposables #373
Conversation
@jnm2 - Could you also please review this PR? |
@aaron-hammond - Could you also please review this PR? |
@@ -148,6 +175,7 @@ public void SetRootInstance(object instance) | |||
Instance = instance; | |||
if (decommission == Decommission.LateBound) | |||
{ | |||
// BOOM! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Smoking gun ...
@@ -89,7 +91,32 @@ public bool RequiresDecommission | |||
/// </summary> | |||
public bool RequiresPolicyRelease | |||
{ | |||
get { return TrackedExternally == false && RequiresDecommission; } | |||
get |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably need a new abstraction.
@@ -380,7 +380,8 @@ public void Factory_created_sealed_non_disposable_services_with_factory_created_ | |||
|
|||
var component = Kernel.Resolve<SealedComponentWithDependency>(); | |||
|
|||
Assert.IsTrue(Kernel.ReleasePolicy.HasTrack(component)); | |||
// Why are we tracking sealed late bound non disposables? This is bonkers. Surely we are only interested in disposable dependencies? | |||
// Assert.IsTrue(Kernel.ReleasePolicy.HasTrack(component)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
(Fyi the commit message has two typos, 'facotry' and 'dispoables.') I don't sense anything wrong about this, though I'm aware that the meat of it may be going over my head a bit. I'd need someone to break down for me the significance of
I'm not sure what 'sealed' means in this context. Do non-disposable instances need to be tracked so that their potentially disposable dependencies can be released at the appropriate time? Another question: is it possible to configure an ad-hoc decommission handler on a non-disposable component?
Can you help me understand what it means to be tracked externally and how we know for sure that whoever is doing the external tracking has all the necessary information? |
Going Dan North on this. Given: Type `Foo` implements IDisposable. Type `Foo` is registered via a Typed Factory using a service type with an interface `IFoo`. Type `Foo` is registered outside of a typed factory with the implementing service type `Foo`. Type `Foo` has a life style of transient for both typed factory and non typed factory registrations. Type `Foo` is a late bound component because of the single initial typed factory registration. Type `Foo` has IsDefault status via the Typed Factory registration. The typed factory method for Foo resolves using the windsor microkernel using the delegate component activator. When: I resolve IFoo. Then: I should have only one instance. I should only track instances once via the release policy for disposables. I should have two burdens from both the typed factory and the non typed factory registration. I should not have to track sealed non disposables at the parent level that consumes disposable dependencies. I do care about dependent disposables for top level graph non disposables.
This was probably added to help guard against misconfigured lifestyles when helpful exceptions were added. I am not sure it is valid anymore. My reasoning is this: Factories are late bound components, from what I can tell they need burdens if they are to be tracked. If factories engage the vanilla resolve mechanism from the MicroKernel inside the factory having 2 burdens is unavoidable but you might end up with the same instance for a transient lifestyle. By extending the burdens to be release policy aware and using HasTrack functionality you can allow this to pass for the same resolution context. Maybe this helpful exception was masking over a potential bug?
You got me there, I will double check for memory leaks with transients. It seems reasonable to think this.
My understanding is when you ask components to be tracked externally you are telling windsor not to wrap them in burdens. The side effect of this if you have to release and dispose yourself. |
Great, thanks for the explanations!
Sorry to make you explain so much! I'm with you this far, but why is it that engaging the vanilla resolve mechanism results in two burdens? And how is it possible for you to end up with the same instance for a transient lifestyle? |
No problem :)
If you have a
Because the factory calls kernel.resolve inside of it, it is effectively passing back the same transient from registration (2) in (3). Bizarrely you can do this without problems when you remove IDisposable from
Looks like Windsor is trying to track Burdens for When doing that that though, a pretty important looking helpful exception no longer get's thrown :) |
Can re-open if we feel necessary. Ref: https://github.com/fir3pho3nixx/Windsor/pull/8 |
Hopefully Krzysztof has some insight. Let me know if you think I might be able to help. |
@jnm2 - Thanks, I deleted the comment after I posted it. Happy to take this forward with @jonorossi with detailed discussions. I think you can definitely help! Let me figure this out a bit more first. :) |
After investigating this issue extensively: #325
Going Dan North on this.
Given:
Type
Foo
implements IDisposable.Type
Foo
is registered via a Typed Factory using a service type with an interfaceIFoo
.Type
Foo
is registered outside of a typed factory with the implementing service typeFoo
.Type
Foo
has a life style of transient for both typed facotry and non typed factory registrations.Type
Foo
is a late bound component because of the single initial typed factory registration.Type
Foo
has IsDefault status via the Typed Factory registration.The typed factory method for Foo resolves using the windsor microkernel using the delegate component activator.
When:
I resolve IFoo.
Then:
I should have only one instance.
I should only track instances once via the release policy for dispoables.
I should have two burdens from both the typed factory and the non typed factory registration.
I should not have to track sealed non disposables at the parent level that consumes disposable dependencies.
I do care about dependent disposables for top level graph non disposables.