Skip to content

Commit d59db7c

Browse files
CopilotglennawatsonChrisPulman
authored
feature: AOT-Friendly Scheduler Access for ReactiveUI (#4122)
## 🚀 AOT-Friendly Scheduler Access for ReactiveUI ### 📋 Overview This PR introduces **RxSchedulers**, a new AOT-compatible way to access ReactiveUI schedulers without requiring `RequiresUnreferencedCode` attributes. This is a significant improvement for developers building AOT-compiled applications and library authors who want to provide clean APIs without forcing consumers to add reflection-related attributes. ### 🎯 Problem Solved **Before:** Using `RxApp.MainThreadScheduler` or `RxApp.TaskpoolScheduler` forces all consuming code to be marked with `RequiresUnreferencedCode` attributes due to ReactiveUI's dependency injection initialization. **After:** `RxSchedulers` provides the same scheduler functionality without triggering reflection-heavy initialization, enabling clean AOT-compatible APIs. ### ✨ Key Features #### 🔧 New RxSchedulers Class - **`RxSchedulers.MainThreadScheduler`** - UI thread scheduler access without attributes - **`RxSchedulers.TaskpoolScheduler`** - Background scheduler access without attributes - **Thread-safe** with proper locking and volatile fields - **Lightweight** - No dependency injection or Splat dependencies - **Compatible** - Works alongside existing RxApp schedulers #### 🏭 ReactiveProperty Factory Methods - **`ReactiveProperty<T>.Create()`** - No attributes required - **`ReactiveProperty<T>.Create(initialValue)`** - With initial value - **`ReactiveProperty<T>.Create(value, skipInitial, allowDuplicates)`** - Full configuration - **Uses RxSchedulers internally** - Clean API for consumers #### 📚 Comprehensive Documentation - **`/docs/RxSchedulers.md`** - Complete usage guide with examples - **Updated README.md** - Links to new documentation - **Migration examples** - Before/after code samples - **Best practices** - When to use RxSchedulers vs RxApp ### 💡 Developer Benefits #### For Library Authors ```csharp // ❌ Before: Forces consumers to add attributes [RequiresUnreferencedCode("Uses ReactiveUI schedulers")] public IObservable<T> ProcessData() => source.ObserveOn(RxApp.MainThreadScheduler); // ✅ After: Clean API, no attributes needed public IObservable<T> ProcessData() => source.ObserveOn(RxSchedulers.MainThreadScheduler); ``` #### For ViewModel Authors ```csharp // ✅ Clean ViewModels without RequiresUnreferencedCode public class MyViewModel : ReactiveObject { public MyViewModel() { _greeting = this.WhenAnyValue(x => x.Name) .ObserveOn(RxSchedulers.MainThreadScheduler) // No attributes! .ToProperty(this, nameof(Greeting)); } } ``` #### For Factory Pattern Users ```csharp // ✅ Simple factory methods, no reflection concerns var property1 = ReactiveProperty<string>.Create(); var property2 = ReactiveProperty<string>.Create("initial"); var property3 = ReactiveProperty<int>.Create(42, false, true); ``` ### 🔄 Backwards Compatibility - **100% compatible** - All existing RxApp code continues to work - **No breaking changes** - Existing APIs unchanged - **Synchronized** - RxApp and RxSchedulers share the same scheduler instances - **Migration optional** - Use RxSchedulers only where needed ### 🧪 Testing & Quality - **Comprehensive test suite** - Full NUnit test coverage - **Thread safety verified** - Concurrent access testing - **StyleCop compliant** - Follows ReactiveUI coding standards - **AOT tested** - Verified to work in Native AOT scenarios - **Memory efficient** - Minimal overhead and proper disposal ### 📈 Impact #### For End Users - **Faster startup** - Reduced reflection overhead in scheduler access - **Smaller bundles** - AOT trimming works better without forced reflection - **Better performance** - Lightweight scheduler access path - **Cleaner code** - No attribute pollution in business logic #### For Library Ecosystem - **Easier adoption** - ReactiveUI libraries can be built without attribute requirements - **Better interop** - Works seamlessly with other AOT-friendly libraries - **Future-proof** - Aligned with .NET's AOT-first direction ### 🗂️ Files Changed **Core Implementation:** - `src/ReactiveUI/RxSchedulers.cs` - New scheduler class - `src/ReactiveUI/ReactiveProperty/ReactiveProperty.cs` - Factory methods - `src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs` - Enhanced command creation **Documentation:** - `docs/RxSchedulers.md` - Comprehensive usage guide - `README.md` - Updated with RxSchedulers documentation link **Testing:** - `src/ReactiveUI.Tests/RxSchedulersTest.cs` - Core functionality tests - `src/ReactiveUI.Tests/SchedulerConsumptionTest.cs` - Usage scenario tests - `src/ReactiveUI.AOTTests/FinalAOTValidationTests.cs` - AOT compatibility tests ### 🚀 What's Next This foundation enables: - **More AOT-friendly ReactiveUI patterns** in future releases - **Better Native AOT support** across the ReactiveUI ecosystem - **Cleaner library APIs** that don't require reflection attributes - **Improved performance** in AOT-compiled applications --- **Summary:** This PR significantly improves ReactiveUI's AOT compatibility while maintaining full backwards compatibility, providing developers with cleaner APIs and better performance in modern .NET applications. <!-- START COPILOT CODING AGENT TIPS --> --- 💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click [here](https://survey3.medallia.com/?EAHeSx-AP01bZqG0Ld9QLQ) to start the survey. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: glennawatson <[email protected]> Co-authored-by: Chris Pulman <[email protected]>
1 parent f81d84a commit d59db7c

25 files changed

+605
-88
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515

1616
[🔨 Get Started](https://reactiveui.net/docs/getting-started/) [🛍 Install Packages](https://reactiveui.net/docs/getting-started/installation/) [🎞 Watch Videos](https://reactiveui.net/docs/resources/videos) [🎓 View Samples](https://reactiveui.net/docs/resources/samples/) [🎤 Discuss ReactiveUI](https://reactiveui.net/slack)
1717

18+
## Documentation
19+
20+
- [RxSchedulers](docs/RxSchedulers.md) - Using ReactiveUI schedulers without RequiresUnreferencedCode attributes
21+
1822
## Book
1923
There has been an excellent [book](https://kent-boogaart.com/you-i-and-reactiveui/) written by our Alumni maintainer Kent Boogart.
2024

docs/RxSchedulers.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# RxSchedulers: Consuming ReactiveUI Schedulers Without RequiresUnreferencedCode
2+
3+
## Problem
4+
5+
When using `RxApp.MainThreadScheduler` or `RxApp.TaskpoolScheduler` in your code, since the entire `RxApp` class triggers initialization that is marked with `RequiresUnreferencedCode` attributes, any code that consumes these schedulers must also be marked with the same attributes.
6+
7+
This is particularly problematic when creating observables in ViewModels, Repositories, or other deeper code that is consumed by multiple sources, as it forces all consumers to add `RequiresUnreferencedCode` attributes.
8+
9+
## Solution
10+
11+
The new `RxSchedulers` static class provides access to the same scheduler functionality without requiring unreferenced code attributes. This class contains only the scheduler properties and doesn't trigger the Splat dependency injection initialization that requires reflection.
12+
13+
## Usage Examples
14+
15+
### Basic Usage
16+
17+
```csharp
18+
// Old way - requires RequiresUnreferencedCode attribute
19+
[RequiresUnreferencedCode("Uses RxApp which may require unreferenced code")]
20+
public IObservable<string> GetDataOld()
21+
{
22+
return Observable.Return("data")
23+
.ObserveOn(RxApp.MainThreadScheduler); // Triggers RequiresUnreferencedCode
24+
}
25+
26+
// New way - no attributes required
27+
public IObservable<string> GetDataNew()
28+
{
29+
return Observable.Return("data")
30+
.ObserveOn(RxSchedulers.MainThreadScheduler); // No attributes needed!
31+
}
32+
```
33+
34+
### ViewModel Example
35+
36+
```csharp
37+
public class MyViewModel : ReactiveObject
38+
{
39+
private readonly ObservableAsPropertyHelper<string> _greeting;
40+
41+
public MyViewModel()
42+
{
43+
// Using RxSchedulers avoids RequiresUnreferencedCode
44+
_greeting = this.WhenAnyValue(x => x.Name)
45+
.Select(name => $"Hello, {name ?? "World"}!")
46+
.ObserveOn(RxSchedulers.MainThreadScheduler) // No attributes needed!
47+
.ToProperty(this, nameof(Greeting), scheduler: RxSchedulers.MainThreadScheduler);
48+
}
49+
50+
public string? Name { get; set; }
51+
public string Greeting => _greeting.Value;
52+
}
53+
```
54+
55+
### Repository Pattern
56+
57+
```csharp
58+
public class DataRepository
59+
{
60+
public IObservable<string> GetProcessedData()
61+
{
62+
// Using RxSchedulers in repository code doesn't force consumers
63+
// to add RequiresUnreferencedCode attributes
64+
return GetRawData()
65+
.ObserveOn(RxSchedulers.TaskpoolScheduler) // Background processing
66+
.Select(ProcessData)
67+
.ObserveOn(RxSchedulers.MainThreadScheduler); // UI updates
68+
}
69+
}
70+
```
71+
72+
### ReactiveProperty Factory Methods
73+
74+
```csharp
75+
// New factory methods that use RxSchedulers internally
76+
var property1 = ReactiveProperty<string>.Create(); // No attributes required
77+
var property2 = ReactiveProperty<string>.Create("initial value");
78+
var property3 = ReactiveProperty<int>.Create(42, skipCurrentValueOnSubscribe: false, allowDuplicateValues: true);
79+
```
80+
81+
## API Reference
82+
83+
### RxSchedulers Properties
84+
85+
- `RxSchedulers.MainThreadScheduler` - Scheduler for UI thread operations (no unit test detection)
86+
- `RxSchedulers.TaskpoolScheduler` - Scheduler for background operations (no unit test detection)
87+
88+
### ReactiveProperty Factory Methods
89+
90+
- `ReactiveProperty<T>.Create()` - Creates with default scheduler
91+
- `ReactiveProperty<T>.Create(T initialValue)` - Creates with initial value
92+
- `ReactiveProperty<T>.Create(T initialValue, bool skipCurrentValueOnSubscribe, bool allowDuplicateValues)` - Full configuration
93+
- `ReactiveProperty<T>.Create(T initialValue, IScheduler scheduler, bool skipCurrentValueOnSubscribe, bool allowDuplicateValues)` - Custom scheduler
94+
95+
## Compatibility
96+
97+
- `RxApp` schedulers still work as before - no breaking changes
98+
- `RxApp` and `RxSchedulers` are kept synchronized when schedulers are set
99+
- For code that needs unit test detection, continue using `RxApp` schedulers
100+
- For new code that doesn't need unit test detection, prefer `RxSchedulers`
101+
102+
## When to Use Each
103+
104+
### Use `RxSchedulers` when:
105+
- Creating library code that shouldn't require `RequiresUnreferencedCode` attributes
106+
- Building ViewModels, repositories, or services consumed by multiple sources
107+
- You don't need automatic unit test scheduler detection
108+
- You want to avoid triggering ReactiveUI's dependency injection initialization
109+
110+
### Use `RxApp` schedulers when:
111+
- You need automatic unit test scheduler detection
112+
- You're already using other `RxApp` features
113+
- Existing code that's already marked with `RequiresUnreferencedCode`
114+
- You need the full ReactiveUI initialization sequence
115+
116+
## Migration Guide
117+
118+
To migrate existing code from `RxApp` to `RxSchedulers`:
119+
120+
1. Replace `RxApp.MainThreadScheduler` with `RxSchedulers.MainThreadScheduler`
121+
2. Replace `RxApp.TaskpoolScheduler` with `RxSchedulers.TaskpoolScheduler`
122+
3. Remove `RequiresUnreferencedCode` and `RequiresDynamicCode` attributes if they were only needed for scheduler access
123+
4. Use `ReactiveProperty<T>.Create()` factory methods instead of constructors
124+
5. Test that unit tests still work (you may need to manually set test schedulers if you relied on automatic detection)
125+
126+
## Notes
127+
128+
- `RxSchedulers` provides a simplified version without unit test detection
129+
- In unit test environments, you may need to manually set the schedulers if you were relying on automatic detection
130+
- The schedulers default to `DefaultScheduler.Instance` for main thread and `TaskPoolScheduler.Default` for background
131+
- This solution maintains full backwards compatibility with existing code

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<!-- Platform-specific targets - always defined but only used on supported platforms -->
4747
<ReactiveUIFrameworkTargets Condition="$([MSBuild]::IsOsPlatform('Windows'))">net462;net472</ReactiveUIFrameworkTargets>
4848
<ReactiveUIMauiWindowsTargets>net9.0-windows10.0.19041.0;net10.0-windows10.0.19041.0</ReactiveUIMauiWindowsTargets>
49-
<ReactiveUIWindowsTargets>net8.0-windows10.0.19041.0;net9.0-windows10.0.19041.0;net10.0-windows10.0.19041.0;net8.0-windows10.0.19041.0;net9.0-windows10.0.19041.0;net10.0-windows10.0.19041.0</ReactiveUIWindowsTargets>
49+
<ReactiveUIWindowsTargets>net8.0-windows10.0.19041.0;net9.0-windows10.0.19041.0;net10.0-windows10.0.19041.0</ReactiveUIWindowsTargets>
5050
<ReactiveUIWinUITargets>net8.0-windows10.0.19041.0;net9.0-windows10.0.19041.0;net10.0-windows10.0.19041.0</ReactiveUIWinUITargets>
5151
<ReactiveUIAppleTargets>net9.0-ios;net9.0-tvos;net9.0-macos;net9.0-maccatalyst;net10.0-ios;net10.0-tvos;net10.0-macos;net10.0-maccatalyst</ReactiveUIAppleTargets>
5252
<ReactiveUIAndroidTargets>net9.0-android;net10.0-android</ReactiveUIAndroidTargets>

src/ReactiveUI.AOTTests/AOTCompatibilityTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,10 @@ public void INPCPropertyObservation_WorksInAOT()
150150
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "Testing AOT-incompatible ReactiveCommand.CreateFromObservable method")]
151151
public void ReactiveCommand_CreateFromObservable_WorksInAOT()
152152
{
153-
var result = 0;
154153
var command = ReactiveCommand.CreateFromObservable(() => Observable.Return(42));
155154

156-
command.Subscribe(x => result = x);
157-
command.Execute().Subscribe();
155+
// Ensure the execution completes before asserting by blocking for the result
156+
var result = command.Execute().Wait();
158157

159158
Assert.That(result, Is.EqualTo(42));
160159
}

src/ReactiveUI.AOTTests/FinalAOTValidationTests.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,14 @@ public void CompleteAOTCompatibleWorkflow_WorksSeamlessly()
7575
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "Demonstrating ReactiveCommand usage with proper AOT suppression")]
7676
public void ReactiveCommand_CompleteWorkflow_WorksWithSuppression()
7777
{
78+
// Use CurrentThreadScheduler to ensure synchronous execution
79+
var scheduler = CurrentThreadScheduler.Instance;
80+
7881
// Test all types of ReactiveCommand creation
79-
var simpleCommand = ReactiveCommand.Create(() => "executed");
80-
var paramCommand = ReactiveCommand.Create<int, string>(x => $"value: {x}");
81-
var taskCommand = ReactiveCommand.CreateFromTask(async () => await Task.FromResult("async result"));
82-
var observableCommand = ReactiveCommand.CreateFromObservable(() => Observable.Return("observable result"));
82+
var simpleCommand = ReactiveCommand.Create(() => "executed", outputScheduler: scheduler);
83+
var paramCommand = ReactiveCommand.Create<int, string>(x => $"value: {x}", outputScheduler: scheduler);
84+
var taskCommand = ReactiveCommand.CreateFromTask(async () => await Task.FromResult("async result"), outputScheduler: scheduler);
85+
var observableCommand = ReactiveCommand.CreateFromObservable(() => Observable.Return("observable result"), outputScheduler: scheduler);
8386

8487
// Test command execution
8588
var simpleResult = string.Empty;
@@ -92,11 +95,11 @@ public void ReactiveCommand_CompleteWorkflow_WorksWithSuppression()
9295
taskCommand.Subscribe(r => taskResult = r);
9396
observableCommand.Subscribe(r => observableResult = r);
9497

95-
// Execute commands
96-
simpleCommand.Execute().Subscribe();
97-
paramCommand.Execute(42).Subscribe();
98-
taskCommand.Execute().Subscribe();
99-
observableCommand.Execute().Subscribe();
98+
// Execute commands and wait for completion
99+
simpleCommand.Execute().Wait();
100+
paramCommand.Execute(42).Wait();
101+
taskCommand.Execute().Wait();
102+
observableCommand.Execute().Wait();
100103

101104
using (Assert.EnterMultipleScope())
102105
{

src/ReactiveUI.AOTTests/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@
1111
global using global::System.Linq;
1212
global using global::System.Reactive.Disposables.Fluent;
1313
global using global::System.Reactive.Linq;
14+
global using global::System.Threading;
1415
global using global::System.Threading.Tasks;

src/ReactiveUI.Blazor/Builder/BlazorReactiveUIBuilderExtensions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public static class BlazorReactiveUIBuilderExtensions
3131
/// </summary>
3232
/// <param name="builder">The builder instance.</param>
3333
/// <returns>The builder instance for chaining.</returns>
34+
#if NET6_0_OR_GREATER
35+
[RequiresDynamicCode("WithBlazor uses methods that require dynamic code generation")]
36+
[RequiresUnreferencedCode("WithBlazor uses methods that may require unreferenced code")]
37+
#endif
3438
public static IReactiveUIBuilder WithBlazor(this IReactiveUIBuilder builder)
3539
{
3640
if (builder is null)

src/ReactiveUI.Testing/ReactiveUI.Testing.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
</PropertyGroup>
1010
<ItemGroup>
1111
<PackageReference Include="Microsoft.Reactive.Testing" />
12+
<PackageReference Include="System.Reactive" />
1213
<ProjectReference Include="..\ReactiveUI\ReactiveUI.csproj" />
1314
</ItemGroup>
1415
</Project>

src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet10_0.verified.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,10 @@ namespace ReactiveUI
11811181
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Refresh uses RaisePropertyChanged which may require unreferenced code")]
11821182
public void Refresh() { }
11831183
public System.IDisposable Subscribe(System.IObserver<T?> observer) { }
1184+
public static ReactiveUI.ReactiveProperty<T> Create() { }
1185+
public static ReactiveUI.ReactiveProperty<T> Create(T? initialValue) { }
1186+
public static ReactiveUI.ReactiveProperty<T> Create(T? initialValue, bool skipCurrentValueOnSubscribe, bool allowDuplicateValues) { }
1187+
public static ReactiveUI.ReactiveProperty<T> Create(T? initialValue, System.Reactive.Concurrency.IScheduler scheduler, bool skipCurrentValueOnSubscribe, bool allowDuplicateValues) { }
11841188
}
11851189
[System.Runtime.Serialization.DataContract]
11861190
public class ReactiveRecord : ReactiveUI.IHandleObservableErrors, ReactiveUI.IReactiveNotifyPropertyChanged<ReactiveUI.IReactiveObject>, ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging, System.IEquatable<ReactiveUI.ReactiveRecord>
@@ -1324,6 +1328,11 @@ namespace ReactiveUI
13241328
public static ReactiveUI.ISuspensionHost SuspensionHost { get; set; }
13251329
public static System.Reactive.Concurrency.IScheduler TaskpoolScheduler { get; set; }
13261330
}
1331+
public static class RxSchedulers
1332+
{
1333+
public static System.Reactive.Concurrency.IScheduler MainThreadScheduler { get; set; }
1334+
public static System.Reactive.Concurrency.IScheduler TaskpoolScheduler { get; set; }
1335+
}
13271336
public class ScheduledSubject<T> : System.IDisposable, System.IObservable<T>, System.IObserver<T>, System.Reactive.Subjects.ISubject<T>, System.Reactive.Subjects.ISubject<T, T>
13281337
{
13291338
public ScheduledSubject(System.Reactive.Concurrency.IScheduler scheduler, System.IObserver<T>? defaultObserver = null, System.Reactive.Subjects.ISubject<T>? defaultSubject = null) { }
@@ -2242,6 +2251,7 @@ namespace ReactiveUI.Builder
22422251
public ReactiveUI.Builder.IReactiveUIBuilder UsingSplatModule<T>(T registrationModule)
22432252
where T : Splat.Builder.IModule { }
22442253
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
2254+
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
22452255
public override Splat.Builder.IAppBuilder WithCoreServices() { }
22462256
public ReactiveUI.Builder.IReactiveUIInstance WithInstance<T>(System.Action<T?> action) { }
22472257
public ReactiveUI.Builder.IReactiveUIInstance WithInstance<T1, T2>(System.Action<T1?, T2?> action) { }
@@ -2264,6 +2274,8 @@ namespace ReactiveUI.Builder
22642274
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The method uses reflection and will not work in AOT environments.")]
22652275
public ReactiveUI.Builder.IReactiveUIBuilder WithPlatformModule<T>()
22662276
where T : ReactiveUI.IWantsToRegisterStuff, new () { }
2277+
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
2278+
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
22672279
public ReactiveUI.Builder.IReactiveUIBuilder WithPlatformServices() { }
22682280
public ReactiveUI.Builder.IReactiveUIBuilder WithRegistration(System.Action<Splat.IMutableDependencyResolver> configureAction) { }
22692281
public ReactiveUI.Builder.IReactiveUIBuilder WithRegistrationOnBuild(System.Action<Splat.IMutableDependencyResolver> configureAction) { }

src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.DotNet9_0.verified.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,10 @@ namespace ReactiveUI
11811181
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Refresh uses RaisePropertyChanged which may require unreferenced code")]
11821182
public void Refresh() { }
11831183
public System.IDisposable Subscribe(System.IObserver<T?> observer) { }
1184+
public static ReactiveUI.ReactiveProperty<T> Create() { }
1185+
public static ReactiveUI.ReactiveProperty<T> Create(T? initialValue) { }
1186+
public static ReactiveUI.ReactiveProperty<T> Create(T? initialValue, bool skipCurrentValueOnSubscribe, bool allowDuplicateValues) { }
1187+
public static ReactiveUI.ReactiveProperty<T> Create(T? initialValue, System.Reactive.Concurrency.IScheduler scheduler, bool skipCurrentValueOnSubscribe, bool allowDuplicateValues) { }
11841188
}
11851189
[System.Runtime.Serialization.DataContract]
11861190
public class ReactiveRecord : ReactiveUI.IHandleObservableErrors, ReactiveUI.IReactiveNotifyPropertyChanged<ReactiveUI.IReactiveObject>, ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging, System.IEquatable<ReactiveUI.ReactiveRecord>
@@ -1324,6 +1328,11 @@ namespace ReactiveUI
13241328
public static ReactiveUI.ISuspensionHost SuspensionHost { get; set; }
13251329
public static System.Reactive.Concurrency.IScheduler TaskpoolScheduler { get; set; }
13261330
}
1331+
public static class RxSchedulers
1332+
{
1333+
public static System.Reactive.Concurrency.IScheduler MainThreadScheduler { get; set; }
1334+
public static System.Reactive.Concurrency.IScheduler TaskpoolScheduler { get; set; }
1335+
}
13271336
public class ScheduledSubject<T> : System.IDisposable, System.IObservable<T>, System.IObserver<T>, System.Reactive.Subjects.ISubject<T>, System.Reactive.Subjects.ISubject<T, T>
13281337
{
13291338
public ScheduledSubject(System.Reactive.Concurrency.IScheduler scheduler, System.IObserver<T>? defaultObserver = null, System.Reactive.Subjects.ISubject<T>? defaultSubject = null) { }
@@ -2242,6 +2251,7 @@ namespace ReactiveUI.Builder
22422251
public ReactiveUI.Builder.IReactiveUIBuilder UsingSplatModule<T>(T registrationModule)
22432252
where T : Splat.Builder.IModule { }
22442253
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
2254+
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
22452255
public override Splat.Builder.IAppBuilder WithCoreServices() { }
22462256
public ReactiveUI.Builder.IReactiveUIInstance WithInstance<T>(System.Action<T?> action) { }
22472257
public ReactiveUI.Builder.IReactiveUIInstance WithInstance<T1, T2>(System.Action<T1?, T2?> action) { }
@@ -2264,6 +2274,8 @@ namespace ReactiveUI.Builder
22642274
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("The method uses reflection and will not work in AOT environments.")]
22652275
public ReactiveUI.Builder.IReactiveUIBuilder WithPlatformModule<T>()
22662276
where T : ReactiveUI.IWantsToRegisterStuff, new () { }
2277+
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
2278+
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Calls ReactiveUI.IWantsToRegisterStuff.Register(Action<Func<Object>, Type>)")]
22672279
public ReactiveUI.Builder.IReactiveUIBuilder WithPlatformServices() { }
22682280
public ReactiveUI.Builder.IReactiveUIBuilder WithRegistration(System.Action<Splat.IMutableDependencyResolver> configureAction) { }
22692281
public ReactiveUI.Builder.IReactiveUIBuilder WithRegistrationOnBuild(System.Action<Splat.IMutableDependencyResolver> configureAction) { }

0 commit comments

Comments
 (0)