Skip to content

Commit 5d4176e

Browse files
authored
Ensure Splat initialization in builder and tests (#4110)
(<!-- Please be sure to read the [Contribute]https://github.com/reactiveui/reactiveui#contribute) section of the README --> **What kind of change does this PR introduce?** <!-- Bug fix, feature, docs update, ... --> update **What is the new behavior?** <!-- If this is a feature change --> This pull request refactors platform-specific builder extension methods for Blazor and AndroidX, consolidating them under the `ReactiveUI.Builder` namespace and updating their APIs for consistency and improved scheduler configuration. It also updates related tests to use the new builder creation method, streamlining service registration and test setup. Minor dependency and warning suppression updates are included. **Platform Extension Refactor and Consolidation:** * Added new extension classes `BlazorReactiveUIBuilderExtensions` and `AndroidXReactiveUIBuilderExtensions` in the `ReactiveUI.Builder` namespace, providing consistent APIs for configuring platform schedulers and modules. These replace the older extension files and introduce properties for main thread schedulers. * Removed legacy extension files `ReactiveUIBuilderBlazorExtensions.cs` and `ReactiveUIBuilderAndroidXExtensions.cs` from platform-specific namespaces, migrating their functionality to the new consolidated location. **Test Suite Modernization:** * Updated all builder-related tests to use `locator.CreateReactiveUIBuilder()` instead of the previous `locator.CreateBuilder()` method, and replaced direct calls to `AppBuilder.ResetBuilderStateForTests()` with `Splat.Builder.AppBuilder.ResetBuilderStateForTests()`. This change ensures tests use the new builder API and maintain proper isolation. **Dependency and Warning Updates:** * Bumped the `SplatVersion` property in `Directory.Packages.props` from `15.5.3` to `16.0.1` to use the latest version. * Added `CA1510` to the `NoWarn` property in `Directory.build.props` to suppress a new code analysis warning. **AOT Test Initialization:** * Ensured that `RxApp.EnsureInitialized()` is called in the constructor of `ViewLocatorAOTMappingTests` to guarantee ReactiveUI is initialized for AOT mapping tests. **What might this PR break?** N/A new unreleased feature **Please check if the PR fulfills these requirements** - [x] Tests for the changes have been added (for bug fixes / features) - [ ] Docs have been added / updated (for bug fixes / features) **Other information**:
1 parent ca35ad6 commit 5d4176e

File tree

57 files changed

+1062
-962
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1062
-962
lines changed

src/Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
1919
<PackageVersion Include="Microsoft.Reactive.Testing" Version="6.0.1" />
2020
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
21-
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4654" />
21+
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4948" />
2222
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.135" />
2323
<PackageVersion Include="Mocks.Maui" Version="1.2.5" />
2424
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.7.115" />

src/Directory.build.props

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<PackageReleaseNotes>https://github.com/reactiveui/ReactiveUI/releases</PackageReleaseNotes>
1818
<RepositoryUrl>https://github.com/reactiveui/reactiveui</RepositoryUrl>
1919
<RepositoryType>git</RepositoryType>
20-
<NoWarn>$(NoWarn);IDE0060;IDE1006;IDE0130;VSSpell001</NoWarn>
20+
<NoWarn>$(NoWarn);IDE0060;IDE1006;IDE0130;VSSpell001;CA1510</NoWarn>
2121
<!-- Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
2222
<PublishRepositoryUrl>true</PublishRepositoryUrl>
2323
<!-- Embed source files that are not tracked by the source control manager in the PDB -->
@@ -35,6 +35,8 @@
3535
<WindowsTargetFrameworks>net462;net472;net8.0-windows10.0.17763.0;net9.0-windows10.0.17763.0;net8.0-windows10.0.19041.0;net9.0-windows10.0.19041.0</WindowsTargetFrameworks>
3636
<MobileTargetFrameworks>net8.0-android;net8.0-ios;net8.0-tvos;net8.0-macos;net8.0-maccatalyst;net9.0-android;net9.0-ios;net9.0-tvos;net9.0-macos;net9.0-maccatalyst</MobileTargetFrameworks>
3737
<BaseTargetFrameworks>netstandard2.0;net8.0;net9.0</BaseTargetFrameworks>
38+
<!-- Ensure all test runs use our runsettings to control cross-assembly parallelism -->
39+
<RunSettingsFilePath>$(MSBuildThisFileDirectory)tests.runsettings</RunSettingsFilePath>
3840
</PropertyGroup>
3941
<PropertyGroup Condition="'$(IsTestProject)' != 'true' and ($(TargetFramework.StartsWith('net8.0')) or $(TargetFramework.StartsWith('net9.0')))">
4042
<IsAotCompatible>true</IsAotCompatible>

src/ReactiveUI.AOTTests/ComprehensiveAOTTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ public void ObservableAsPropertyHelper_StringBased_WorksInAOT()
161161
[Fact]
162162
public void DependencyInjection_BasicUsage_WorksInAOT()
163163
{
164+
Splat.Builder.AppBuilder.ResetBuilderStateForTests();
165+
164166
// Basic DI operations that work in AOT
165167
var resolver = Locator.CurrentMutable;
166168

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
[assembly: CollectionBehavior(DisableTestParallelization = true, MaxParallelThreads = 1)]
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using System.Reactive.Concurrency;
7+
8+
namespace ReactiveUI.Builder;
9+
10+
/// <summary>
11+
/// AndroidX-specific extensions for the ReactiveUI builder.
12+
/// </summary>
13+
public static class AndroidXReactiveUIBuilderExtensions
14+
{
15+
/// <summary>
16+
/// Gets the android x main thread scheduler.
17+
/// </summary>
18+
/// <value>
19+
/// The android x main thread scheduler.
20+
/// </value>
21+
public static IScheduler AndroidXMainThreadScheduler { get; } = HandlerScheduler.MainThreadScheduler;
22+
23+
/// <summary>
24+
/// Configures ReactiveUI for AndroidX platform with appropriate schedulers.
25+
/// </summary>
26+
/// <param name="builder">The builder instance.</param>
27+
/// <returns>The builder instance for chaining.</returns>
28+
public static ReactiveUIBuilder WithAndroidX(this ReactiveUIBuilder builder)
29+
{
30+
if (builder is null)
31+
{
32+
throw new ArgumentNullException(nameof(builder));
33+
}
34+
35+
return builder
36+
.WithMainThreadScheduler(HandlerScheduler.MainThreadScheduler)
37+
.WithPlatformModule<AndroidX.Registrations>();
38+
}
39+
40+
/// <summary>
41+
/// Withes the android x scheduler.
42+
/// </summary>
43+
/// <param name="builder">The builder.</param>
44+
/// <returns>The builder instance for chaining.</returns>
45+
public static ReactiveUIBuilder WithAndroidXScheduler(this ReactiveUIBuilder builder)
46+
{
47+
if (builder is null)
48+
{
49+
throw new ArgumentNullException(nameof(builder));
50+
}
51+
52+
return builder.WithMainThreadScheduler(AndroidXMainThreadScheduler);
53+
}
54+
}

src/ReactiveUI.AndroidX/ReactiveUIBuilderAndroidXExtensions.cs

Lines changed: 0 additions & 57 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
namespace ReactiveUI.Builder;
7+
8+
/// <summary>
9+
/// Blazor-specific extensions for the ReactiveUI builder.
10+
/// </summary>
11+
public static class BlazorReactiveUIBuilderExtensions
12+
{
13+
/// <summary>
14+
/// Gets the blazor main thread scheduler.
15+
/// </summary>
16+
/// <value>
17+
/// The blazor main thread scheduler.
18+
/// </value>
19+
public static IScheduler BlazorMainThreadScheduler { get; } = CurrentThreadScheduler.Instance;
20+
21+
/// <summary>
22+
/// Configures ReactiveUI for Blazor platform with appropriate schedulers.
23+
/// </summary>
24+
/// <param name="builder">The builder instance.</param>
25+
/// <returns>The builder instance for chaining.</returns>
26+
public static ReactiveUIBuilder WithBlazor(this ReactiveUIBuilder builder)
27+
{
28+
if (builder is null)
29+
{
30+
throw new ArgumentNullException(nameof(builder));
31+
}
32+
33+
return builder
34+
.WithBlazorScheduler()
35+
.WithPlatformModule<Blazor.Registrations>();
36+
}
37+
38+
/// <summary>
39+
/// Withes the blazor scheduler.
40+
/// </summary>
41+
/// <param name="builder">The builder.</param>
42+
/// <returns>The builder instance for chaining.</returns>
43+
public static ReactiveUIBuilder WithBlazorScheduler(this ReactiveUIBuilder builder)
44+
{
45+
if (builder is null)
46+
{
47+
throw new ArgumentNullException(nameof(builder));
48+
}
49+
50+
return builder.WithMainThreadScheduler(BlazorMainThreadScheduler);
51+
}
52+
}

src/ReactiveUI.Blazor/ReactiveUIBuilderBlazorExtensions.cs

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/ReactiveUI.Builder.Maui.Tests/ReactiveUIBuilderMauiTests.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// The .NET Foundation licenses this file to you under the MIT license.
44
// See the LICENSE file in the project root for full license information.
55

6-
using ReactiveUI.Maui;
76
using Splat.Builder;
87

98
namespace ReactiveUI.Builder.Maui.Tests;
@@ -16,21 +15,7 @@ public void WithMaui_Should_Register_Services()
1615
AppBuilder.ResetBuilderStateForTests();
1716
using var locator = new ModernDependencyResolver();
1817

19-
locator.CreateBuilder()
20-
.WithMaui()
21-
.Build();
22-
23-
var typeConverters = locator.GetServices<IBindingTypeConverter>();
24-
Assert.NotNull(typeConverters);
25-
}
26-
27-
[Fact]
28-
public void WithCoreServices_AndMaui_Should_Register_All_Services()
29-
{
30-
AppBuilder.ResetBuilderStateForTests();
31-
using var locator = new ModernDependencyResolver();
32-
33-
locator.CreateBuilder()
18+
locator.CreateReactiveUIBuilder()
3419
.WithMaui()
3520
.Build();
3621

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
[assembly: CollectionBehavior(DisableTestParallelization = true, MaxParallelThreads = 1)]

0 commit comments

Comments
 (0)