| name | reactiveui-primitives |
|---|---|
| description | Use when working with ReactiveUI.Primitives NuGet packages in .NET projects, including ReactiveUI.Disposables, ReactiveUI.Primitives.Core, ReactiveUI.Primitives, ReactiveUI.Primitives.Reactive, ReactiveUI.Primitives.Async.Core, ReactiveUI.Primitives.Async, ReactiveUI.Primitives.Async.Reactive, ReactiveUI.Primitives.R3Bridge.Generator, ReactiveUI.Primitives.Wpf, ReactiveUI.Primitives.Wpf.Reactive, ReactiveUI.Primitives.WinForms, ReactiveUI.Primitives.WinForms.Reactive, ReactiveUI.Primitives.WinUI, ReactiveUI.Primitives.WinUI.Reactive, ReactiveUI.Primitives.Blazor, ReactiveUI.Primitives.Blazor.Reactive, ReactiveUI.Primitives.Avalonia, ReactiveUI.Primitives.Avalonia.Reactive, ReactiveUI.Primitives.Maui, or ReactiveUI.Primitives.Maui.Reactive; choosing Core vs lean vs System.Reactive package variants; using IObservable, IObservableAsync, signals, extension helpers, sequencers, disposable helpers, UI dispatch adapters, R3/R3Async generated bridges, or migration guidance from System.Reactive/R3/R3Async repositories to Primitives or .Reactive package variants. |
Use this skill when adding or using ReactiveUI.Primitives packages. Prefer NuGet package guidance over repository project references unless the user is explicitly editing this repository.
Default to the non-Core leaf packages for applications. Choose Core packages only for library authors or advanced composition work that needs the shared type layer without the full leaf surface.
| Package | Use when | Key APIs and notes |
|---|---|---|
ReactiveUI.Disposables |
The project only needs disposable lifetime helpers. | ReactiveUI.Primitives.Disposables; Scope, MultipleDisposable, DisposableBag, Pocket, Slot, AssignmentSlot, SingleDisposable, SingleReplaceableDisposable, MutableDisposable, SwapDisposable, OnceDisposable, BooleanDisposable, CancellationDisposable, EmptyDisposable. |
ReactiveUI.Primitives.Core |
Building a low-level library that needs the shared Primitives type layer without the full leaf package. | Root namespace remains ReactiveUI.Primitives. Includes core signal/state contracts, concurrency contracts, advanced witnesses, and type-agnostic extension-helper support under ReactiveUI.Primitives.Extensions. Depends on ReactiveUI.Disposables. |
ReactiveUI.Primitives |
Most BCL IObservable<T> usage, including migrated ReactiveUI.Extensions helpers. |
Lean package using Primitives RxVoid and ISequencer. Includes signal factories/operators, sequencers, virtual time, and extension helpers under ReactiveUI.Primitives.Extensions. Depends on ReactiveUI.Primitives.Core and ReactiveUI.Disposables; no separate Extensions package is required. |
ReactiveUI.Primitives.Reactive |
The project is System.Reactive-first and wants Primitives operators and extension helpers compiled with System.Reactive.Unit and IScheduler. |
Uses .Reactive namespaces plus ReactiveUI.Primitives.Extensions.Reactive. Adds System.Reactive and depends on ReactiveUI.Primitives.Core. This is a package variant, not a source-generator bridge; no separate Extensions Reactive package is required. |
ReactiveUI.Primitives.Async.Core |
Building a low-level async library around Primitives async contracts. | ReactiveUI.Primitives.Async; IObservableAsync<T>, IObserverAsync<T>, SignalAsync<T>, SignalAsync, async signal factories, async operators, async disposables, helpers, and async signal implementations. Depends on ReactiveUI.Primitives.Core. |
ReactiveUI.Primitives.Async |
The app needs async-native observable pipelines where observer calls can await or observe cancellation. | Lean async leaf using Primitives RxVoid and ISequencer. Adds AsyncContext, ContextSwitchSignalAsync<T>, SignalAsyncReactiveExtensions, Yield, WitnessOn, ObserveOnSafe, and ObserveOnIf. Depends on ReactiveUI.Primitives and ReactiveUI.Primitives.Async.Core. |
ReactiveUI.Primitives.Async.Reactive |
Async-native pipelines in a System.Reactive-first project. | System.Reactive-flavoured async leaf with System.Reactive.Unit and IScheduler conventions. Depends on ReactiveUI.Primitives.Reactive and ReactiveUI.Primitives.Async.Core. |
ReactiveUI.Primitives.R3Bridge.Generator |
The project needs generated adapters at R3 or R3Async boundaries. | Standalone netstandard2.0 analyzer package. It emits bridges only when the consuming compilation already references the required R3/R3Async symbols; it is not embedded in or required by the runtime packages. |
ReactiveUI.Primitives.Wpf |
WPF UI code needs dispatcher marshalling. | ReactiveUI.Primitives.Concurrency.DispatcherSequencer. Depends on ReactiveUI.Primitives. |
ReactiveUI.Primitives.Wpf.Reactive |
WPF UI code is System.Reactive-first and needs dispatcher scheduling. | ReactiveUI.Primitives.Reactive.Concurrency.DispatcherSequencer implements System.Reactive scheduling conventions. Depends on ReactiveUI.Primitives.Reactive. |
ReactiveUI.Primitives.WinForms |
Windows Forms UI code needs control-thread marshalling. | ReactiveUI.Primitives.Concurrency.ControlSequencer. Depends on ReactiveUI.Primitives. |
ReactiveUI.Primitives.WinForms.Reactive |
Windows Forms UI code is System.Reactive-first and needs control-thread scheduling. | ReactiveUI.Primitives.Reactive.Concurrency.ControlSequencer. Depends on ReactiveUI.Primitives.Reactive. |
ReactiveUI.Primitives.WinUI |
WinUI code needs DispatcherQueue marshalling. |
ReactiveUI.Primitives.Concurrency.DispatcherQueueSequencer and DispatcherQueueSequencerExtensions.ToSequencer(). Depends on ReactiveUI.Primitives and Microsoft.WindowsAppSDK. |
ReactiveUI.Primitives.WinUI.Reactive |
WinUI code is System.Reactive-first and needs DispatcherQueue scheduling. |
ReactiveUI.Primitives.Reactive.Concurrency.DispatcherQueueSequencer and DispatcherQueueSequencerExtensions.ToSequencer(). Depends on ReactiveUI.Primitives.Reactive and Microsoft.WindowsAppSDK. |
ReactiveUI.Primitives.Blazor |
Blazor components need render-thread sequencing and component-bound subscriptions. | ReactiveUI.Primitives.Blazor.Components.ReactiveComponentBase, Observe, Track, InvalidateAsync, ReactiveUI.Primitives.Blazor.Concurrency.BlazorRendererSequencer. Depends on ReactiveUI.Primitives and Microsoft.AspNetCore.Components. |
ReactiveUI.Primitives.Blazor.Reactive |
Blazor components are System.Reactive-first and need render-thread scheduling. | ReactiveUI.Primitives.Blazor.Reactive.Components.ReactiveComponentBase and ReactiveUI.Primitives.Blazor.Reactive.Concurrency.BlazorRendererSequencer. Depends on ReactiveUI.Primitives.Reactive and Microsoft.AspNetCore.Components. |
ReactiveUI.Primitives.Avalonia |
Avalonia UI code needs dispatcher marshalling. | ReactiveUI.Primitives.Concurrency.AvaloniaScheduler; Instance uses Dispatcher.UIThread at background priority, or construct with a Dispatcher and optional DispatcherPriority. Depends on ReactiveUI.Primitives and Avalonia. |
ReactiveUI.Primitives.Avalonia.Reactive |
Avalonia UI code is System.Reactive-first and needs dispatcher scheduling. | ReactiveUI.Primitives.Reactive.Concurrency.AvaloniaScheduler; Instance uses Dispatcher.UIThread at background priority, or construct with a Dispatcher and optional DispatcherPriority. Depends on ReactiveUI.Primitives.Reactive and Avalonia. |
ReactiveUI.Primitives.Maui |
.NET MAUI code needs dispatcher marshalling. | ReactiveUI.Primitives.Concurrency.MauiDispatcherSequencer and MauiDispatcherSequencerExtensions.ToSequencer(). Depends on ReactiveUI.Primitives and Microsoft.Maui.Core. |
ReactiveUI.Primitives.Maui.Reactive |
.NET MAUI code is System.Reactive-first and needs dispatcher scheduling. | ReactiveUI.Primitives.Reactive.Concurrency.MauiDispatcherSequencer and MauiDispatcherSequencerExtensions.ToSequencer(). Depends on ReactiveUI.Primitives.Reactive and Microsoft.Maui.Core. |
Install examples:
dotnet add package ReactiveUI.Primitives
dotnet add package ReactiveUI.Primitives.Async
dotnet add package ReactiveUI.Primitives.Wpf
dotnet add package ReactiveUI.Primitives.AvaloniaUse .Core packages deliberately:
dotnet add package ReactiveUI.Primitives.Core
dotnet add package ReactiveUI.Primitives.Async.CoreUse .Reactive packages when the project already uses System.Reactive idioms:
dotnet add package ReactiveUI.Primitives.Reactive
dotnet add package ReactiveUI.Primitives.Async.Reactive
dotnet add package ReactiveUI.Primitives.Wpf.Reactive
dotnet add package ReactiveUI.Primitives.Avalonia.ReactiveAdd ReactiveUI.Primitives.R3Bridge.Generator only when the project needs generated R3 or R3Async bridge methods. It is
a standalone analyzer package and is not embedded in the runtime packages.
dotnet add package ReactiveUI.Primitives.R3Bridge.Generator- Prefer
ReactiveUI.Primitivesfor new app code that uses BCLIObservable<T>. - Prefer
ReactiveUI.Primitives.Asyncwhen subscription, notification, or completion work must be asynchronous. - Prefer
ReactiveUI.Primitivesfor migrated helper operators from ReactiveUI.Extensions-style code; their existingReactiveUI.Primitives.Extensionsnamespace is retained. - Prefer UI packages only in the matching UI framework; use the lean UI package for
ISequencerand the.ReactiveUI package forIScheduler. - For Avalonia UI dispatch, choose
ReactiveUI.Primitives.Avalonia; chooseReactiveUI.Primitives.Avalonia.Reactiveonly when the project is System.Reactive-first. - Prefer
.Reactivevariants when public APIs should exposeSystem.Reactive.Unit,IScheduler,.Reactivenamespaces, or existing Rx source should compile with minimal code changes. - Prefer
.Corevariants only when composing packages or minimizing a library dependency layer. Most apps should reference the leaf package. - Avoid mixing lean and
.Reactivevariants in the same pipeline without an explicit boundary; their namespaces and scheduler/unit conventions differ. - Do not add
System.Reactivejust to use core Primitives. The.Reactivepackages add it for System.Reactive-first projects. - Do not expect a System.Reactive bridge generator. System.Reactive support is provided by the explicit
.Reactivepackage variants.
Lean synchronous packages:
using ReactiveUI.Primitives;
using ReactiveUI.Primitives.Advanced;
using ReactiveUI.Primitives.Concurrency;
using ReactiveUI.Primitives.Core;
using ReactiveUI.Primitives.Disposables;
using ReactiveUI.Primitives.Signals;Async packages:
using ReactiveUI.Primitives.Async;
using ReactiveUI.Primitives.Async.Disposables;
using ReactiveUI.Primitives.Async.Signals;Extension namespaces provided by the base packages:
using ReactiveUI.Primitives.Extensions;
using ReactiveUI.Primitives.Extensions.Operators;System.Reactive-flavoured packages:
using ReactiveUI.Primitives.Reactive;
using ReactiveUI.Primitives.Reactive.Concurrency;
using ReactiveUI.Primitives.Reactive.Signals;
using ReactiveUI.Primitives.Extensions.Reactive;Reactive UI packages expose lean sequencers under ReactiveUI.Primitives.Concurrency and System.Reactive schedulers
under ReactiveUI.Primitives.Reactive.Concurrency. Blazor also exposes component helpers under
ReactiveUI.Primitives.Blazor.Reactive.Components. Avalonia exposes AvaloniaScheduler in both concurrency namespaces;
its ready work is coalesced into one dispatcher drain and delayed work uses dispatcher-bound timers.
R3 generated bridges:
using ReactiveUI.Primitives.R3Bridge;Use these landmarks to choose APIs quickly; rely on IntelliSense/PublicAPI for exact overloads.
- Signals and factories:
Signal,Signal<T>,BehaviorSignal<T>,StateSignal<T>,ReplaySignal<T>,ScheduledSignal<T>,PrioritySemaphoreSignal<T>,AnonymousSignal<T>,ConnectableSignal<T>. - State and commands:
ReadOnlyState<T>,CommandSignal<TResult>,CommandExecution<TResult>,TaskSignal,TaskSignal<T>. - Sequencing:
ISequencer,CurrentThreadSequencer,ImmediateSequencer,SynchronizationContextSequencer,TaskPoolSequencer,ThreadPoolSequencer,VirtualTimeSequencer<TAbsolute, TRelative>,VirtualClock. - Operators:
Map,FlatMap,Bind,SelectMany,Where,Keep,KeepNotNull,Cast,Concat,Merge,Amb,Race,Switch,Retry,Recover,Rescue,Distinct,Take,Skip,Collect,Materialize,Dematerialize,ForkJoin,Pair,Latch,SyncLatest,CombineLatest,Synchronize,Timeout,Shift,Spark,Unspark.SyncLatestand Rx-nameCombineLatestsupport up to 16 total sources; Rx-nameSelectManyobservable overloads preserve concurrent merge semantics. - Connectable helpers:
Replay,ReplayLive,Share,ShareLatest,AutoConnect,AutoShare. - Async core:
IObservableAsync<T>,IObserverAsync<T>,SignalAsync<T>,SignalAsync,WitnessAsync<T>,ConnectableSignalAsync<T>,ConcurrentWitnessCallsException. - Async factories/operators:
SignalAsync.Create,Return,Range,FromAsync,FromAsyncEnumerable,Every,Interval,Timer,Using,Blend,Chain,Map,Merge,CombineLatest,Switch,ForEachAsync,Collect*Async,WaitCompletionAsync,OnErrorResumeAsFailure. - Extension helpers:
AsSignal,BufferUntil,BufferUntilIdle,DebounceImmediate,DebounceUntil,DetectStale,Filter,Heartbeat,ObserveOnSafe,ObserveOnIf,Pairwise,Partition,ReplayLastOnSubscribe,RetryWithBackoff,RetryWithDelay,RetryForeverWithDelay,RunAll,Shuffle,SwitchIfEmpty,Throttle*,ToHotTask,ToHotValueTask,WaitUntil.Filter(string)uses a 30-second regex timeout;Filter(Regex)preserves caller-supplied options and timeout.
Use this process when moving an Rx-based repository to ReactiveUI.Primitives. Decide first whether the immediate target
is a lean Primitives project, a System.Reactive-compatible .Reactive project, or both.
Use this path when the existing project should stop exposing System.Reactive Unit, IScheduler, and package
dependencies.
- Inventory package references and public APIs. Find
System.Reactive,System.Reactive.Linq,System.Reactive.Subjects,System.Reactive.Disposables,System.Reactive.Concurrency,ReactiveUI.Extensions,Unit,IScheduler,Subject<T>,BehaviorSubject<T>,ReplaySubject<T>, andTestScheduler. - Add the smallest lean package set:
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives.Async- Add only the matching lean UI package when UI dispatch is used:
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives.Wpf
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives.WinForms
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives.WinUI
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives.Blazor
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives.Avalonia
dotnet add xyz/xyz.csproj package ReactiveUI.Primitives.Maui- Convert types at boundaries:
Unit->RxVoid,IScheduler->ISequencer,Subject<T>->Signal<T>,BehaviorSubject<T>->StateSignal<T>,ReplaySubject<T>->ReplaySignal<T>,AsyncSubject<T>->FinalSignal<T>,CompositeDisposable->MultipleDisposableorPocket,SerialDisposable->SingleReplaceableDisposableorSlot. - Convert factories:
Observable.Return->Signal.Emit,Empty->Signal.None,Never->Signal.Silent,Throw->Signal.Fail,Range->Signal.Sequence,Defer->Signal.Lazy,Timer->Signal.After,Interval->Signal.PulseorSignal.Every,Create->Signal.CreateorSignal.CreateSafe. - Keep code compiling with Rx-name compatibility aliases where useful:
Select,Where,Aggregate,Scan,Merge,Concat,SelectMany,CombineLatest,WithLatestFrom,Throttle, and related names exist on the Primitives surface. - Prefer Primitives names in new or hot-path code:
Map,Keep,Reduce,Fold,Blend,Chain,FlatMap/Bind,SyncLatest,Latch,Calm/Stabilize,Probe,Shift,Expire. - Replace schedulers with
Sequencer.Immediate,Sequencer.CurrentThread,ThreadPoolSequencer.Instance,TaskPoolSequencer.Instance,SynchronizationContextSequencer, UI sequencers, orVirtualClockfor tests. - Remove System.Reactive and ReactiveUI.Extensions package references only after imports and public APIs no longer require them. Keep bridge conversions at package edges.
Use this path when an Rx-based source base should keep System.Reactive-facing APIs for existing consumers while sharing
implementation with a lean xyz package.
- Create
xyz.Reactiveas a sibling project toxyz. Link or share implementation files instead of copying logic. - In shared implementation code, use neutral identifiers
RxVoidandISequencer. The lean project binds them to Primitives types; the reactive project aliases them toSystem.Reactive.UnitandSystem.Reactive.Concurrency.IScheduler. - Gate namespaces when package namespaces differ:
#if REACTIVE_SHIM
namespace xyz.Reactive;
#else
namespace xyz;
#endif- Add the
.Reactivepackage set that matches the source surface:
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.Reactive
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.Async.Reactive- Add only the matching
.ReactiveUI package when the project exposes UI scheduling:
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.Wpf.Reactive
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.WinForms.Reactive
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.WinUI.Reactive
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.Blazor.Reactive
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.Avalonia.Reactive
dotnet add xyz.Reactive/xyz.Reactive.csproj package ReactiveUI.Primitives.Maui.Reactive- If the repository does not centralize this already, configure
xyz.Reactive:
<PropertyGroup>
<DefineConstants>$(DefineConstants);REACTIVE_SHIM</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Reactive.Unit" Alias="RxVoid" />
<Using Include="System.Reactive.Concurrency.IScheduler" Alias="ISequencer" />
</ItemGroup>- Preserve Rx source compatibility first. Keep names such as
Select,Where,SelectMany,CombineLatest,Merge,Concat,Throttle, andWithLatestFromwhen that avoids unnecessary code churn. The.Reactivepackages provide those names over the Primitives implementation. - Build
xyzandxyz.Reactiveside by side. The leanxyzpackage should avoid System.Reactive runtime dependencies;xyz.Reactiveintentionally references System.Reactive and exposesUnit/IScheduler. - Update tests to run both package variants. Prefer TUnit/Microsoft Testing Platform in this repository and use only TUnit assertions.
R3 bridges are generated into the consuming assembly only when the consumer references
ReactiveUI.Primitives.R3Bridge.Generator and already references the required R3 symbols. The generated namespace is
ReactiveUI.Primitives.R3Bridge.
When R3.Observable<T> is visible, the generator emits:
AsPrimitivesSignal<T>(this R3.Observable<T>)AsR3Observable<T>(this System.IObservable<T>)
When both R3.Observable<T> and ReactiveUI.Primitives.Async.IObservableAsync<T> are visible, the generator emits:
AsPrimitivesAsyncObservable<T>(this R3.Observable<T>)AsR3Observable<T>(this IObservableAsync<T>)
When R3Async.AsyncObservable<T>, R3Async.AsyncObserver<T>, R3Async.Result, and IObservableAsync<T> are visible,
the async bridge generator emits:
AsPrimitivesAsyncObservable<T>(this R3Async.AsyncObservable<T>)AsR3AsyncObservable<T>(this IObservableAsync<T>)
Use bridge methods only at boundaries. Keep internal pipelines in one model after conversion.
ReactiveUI.Disposables,ReactiveUI.Primitives.Core,ReactiveUI.Primitives.Async.Core,ReactiveUI.Primitives.Async, andReactiveUI.Primitives.Async.Reactivetargetnet8.0,net9.0,net10.0,net11.0,net462,net472,net48, andnet481.ReactiveUI.Primitives.R3Bridge.Generatortargetsnetstandard2.0.ReactiveUI.PrimitivesandReactiveUI.Primitives.Reactivetarget the same eight general-library TFMs plusnet10.0-androidandnet11.0-android; on Windows or macOS they also target net10/net11 iOS, tvOS, macOS, and Mac Catalyst for platform sequencers.- WPF and WinForms packages, including
.Reactivevariants, targetnet8.0-windowsthroughnet11.0-windowsplusnet462,net472,net48, andnet481. - WinUI packages, including
.Reactivevariants, targetnet8.0-windows10.0.19041.0throughnet11.0-windows10.0.19041.0. - Avalonia packages, including
.Reactivevariants, targetnet8.0,net9.0,net10.0, andnet11.0and referenceAvalonia. - MAUI packages, including
.Reactivevariants, targetnet10.0andnet11.0. - Blazor packages, including
.Reactivevariants, targetnet8.0,net9.0,net10.0, andnet11.0.
When editing this repository:
- Use
src/ReactiveUI.Primitives.slnxas the solution entrypoint. - Build and test from
src. - Tests use Microsoft.Testing.Platform with TUnit; write TUnit tests and TUnit assertions only.
- Shipping public API baselines live under each package's
PublicAPI/<tfm>/PublicAPI.Shipped.txtandPublicAPI.Unshipped.txt. Skill.mdis the canonical skill file.ReactiveUI.Primitives.csprojpacks it both at package root asSkill.mdand at.agents/skills/reactiveui-primitives/SKILL.md; keep this filename singular and casing intact.- Keep package guidance synchronized with packable projects in the solution. Tests and benchmarks are not NuGet packages to add directly.