feat(reactive): add ContainerDisposable for CompositeDisposable interop - #169
Merged
Merged
Conversation
- Add ContainerDisposable, a MultipleDisposable that converts implicitly to a CompositeDisposable it owns and disposes, so a disposal group flows into APIs written against System.Reactive without a hand conversion. - MultipleDisposable ships in the dependency-free ReactiveUI.Disposables package and cannot name CompositeDisposable, so the seam has to live here. - Add a DisposeWith overload taking the container. Without it a call site that imports this namespace and System.Reactive's fluent disposal helpers has two equally-good candidates and is ambiguous.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #169 +/- ##
==========================================
+ Coverage 98.14% 98.15% +0.01%
==========================================
Files 703 705 +2
Lines 21733 21761 +28
Branches 2679 2680 +1
==========================================
+ Hits 21330 21360 +30
+ Misses 199 197 -2
Partials 204 204 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ChrisPulman
approved these changes
Aug 19, 2026
|
The lifetimes are only tied in one direction. If the user loses the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What kind of change does this PR introduce?
Feature - new public API on
ReactiveUI.Primitives.Reactive.What is the new behavior?
ReactiveUI.Primitives.ReactiveshipsContainerDisposable, a disposal group a System.Reactive consumer can use as aCompositeDisposable.ContainerDisposableis aMultipleDisposablethat converts implicitly to aCompositeDisposableit owns.DisposeWith, to a library that takes aCompositeDisposable, or to your own helper - no conversion at the call site.MultipleDisposable.Add.Clear()andRemove()dispose the composite along with everything else; the next conversion hands back a fresh one, so the container stays usable.DisposeWithgains an overload that takes the container. A container is convertible toCompositeDisposable, so without this overload a call site importing bothReactiveUI.Primitives.Reactiveand System.Reactive's fluent disposal helpers has two equally-good candidates and does not compile. Taking the container exactly makes this an identity match, which wins outright.The intended consumer is
ReactiveUI.Reactive, whoseWhenActivated(Action<MultipleDisposable>)overloads can hand out aContainerDisposableinstead. That is a follow-up in the ReactiveUI repo and is blocked on this shipping - ReactiveUI consumes Primitives as a package reference.What is the current behavior?
MultipleDisposableships inReactiveUI.Disposables, which deliberately has no System.Reactive dependency, so it cannot nameCompositeDisposableand no conversion between them exists. Code that gets aMultipleDisposablefromWhenActivatedand calls System.Reactive'sDisposeWithon it does not compile; the workaround is to importReactiveUI.Primitives.Reactivefor the PrimitivesDisposeWithinstead.Relates to reactiveui/ReactiveUI#4434.
What might this PR break?
None. The change is additive:
ContainerDisposableis new, and the existingDisposeWith(MultipleDisposable)overload is untouched.DisposeWithbinds to the new overload by identity, so the two overloads coexist whether or not System.Reactive's fluent disposal helpers are also imported.Two things worth knowing when using it:
ICollection<IDisposable>view counts the composite as a single entry.Count,ContainsandRemovedo not see through it to registrations made on the composite..Reactiveflavour.Checklist
mainbranchAdditional information
The hand-written files are
ContainerDisposable.cs,LinqExtensions.ContainerDisposable.cs,ContainerDisposableTests.cs, the added tests inLinqExtensionsTests.cs, and a README paragraph. The rest of the diff is the same two entries repeated across the per-TFM public API baselines.LinqExtensionsTests.csnow importsSystem.Reactive.Disposables.Fluentdeliberately: that import is what makes the overload-resolution guard a compile-time test rather than a comment.