Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public static IReactiveUIBuilder WithAndroidX(this IReactiveUIBuilder builder)

return builder
.WithMainThreadScheduler(HandlerScheduler.MainThreadScheduler)
.WithTaskPoolScheduler(TaskPoolScheduler.Default)
.WithPlatformModule<AndroidX.Registrations>();
}

Expand Down
19 changes: 19 additions & 0 deletions src/ReactiveUI.Blazor/Builder/BlazorReactiveUIBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,25 @@ public static IReactiveUIBuilder WithBlazor(this IReactiveUIBuilder builder)

return builder
.WithBlazorScheduler()
.WithTaskPoolScheduler(TaskPoolScheduler.Default)
.WithPlatformModule<Blazor.Registrations>();
}

/// <summary>
/// Configures ReactiveUI for Blazor platform with appropriate schedulers.
/// </summary>
/// <param name="builder">The builder instance.</param>
/// <returns>The builder instance for chaining.</returns>
public static IReactiveUIBuilder WithBlazorWasm(this IReactiveUIBuilder builder)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}

return builder
.WithBlazorWasmScheduler()
.WithTaskPoolScheduler(TaskPoolScheduler.Default)
.WithPlatformModule<Blazor.Registrations>();
}

Expand Down
3 changes: 0 additions & 3 deletions src/ReactiveUI.Blazor/Registrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,5 @@ public void Register(IRegistrar registrar)
{
PlatformEnlightenmentProvider.Current.EnableWasm();
}

RxSchedulers.TaskpoolScheduler = TaskPoolScheduler.Default;
RxSchedulers.MainThreadScheduler = CurrentThreadScheduler.Instance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public static IReactiveUIBuilder WithMaui(this IReactiveUIBuilder builder, IDisp

return builder
.WithMauiScheduler(dispatcher)
.WithTaskPoolScheduler(TaskPoolScheduler.Default)
.WithPlatformModule<Maui.Registrations>()
.WithPlatformServices();
}
Expand Down
6 changes: 0 additions & 6 deletions src/ReactiveUI.Maui/Registrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@ public void Register(IRegistrar registrar)
registrar.RegisterConstant<IPropertyBindingHook>(static () => new AutoDataTemplateBindingHook());
registrar.RegisterConstant<IBindingFallbackConverter>(static () => new ComponentModelFallbackConverter());

if (!ModeDetector.InUnitTestRunner())
{
RxSchedulers.MainThreadScheduler = new WaitForDispatcherScheduler(static () => DispatcherQueueScheduler.Current);
RxSchedulers.TaskpoolScheduler = TaskPoolScheduler.Default;
}

RxSchedulers.SuppressViewCommandBindingMessage = true;
#endif
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static IReactiveUIBuilder WithWinUI(this IReactiveUIBuilder builder)

return builder
.WithWinUIScheduler()
.WithTaskPoolScheduler(TaskPoolScheduler.Default)
.WithPlatformModule<WinUI.Registrations>();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public static IReactiveUIBuilder WithWinForms(this IReactiveUIBuilder builder)

return builder
.WithMainThreadScheduler(WinFormsMainThreadScheduler)
.WithTaskPoolScheduler(TaskPoolScheduler.Default)
.WithPlatformModule<Winforms.Registrations>();
}

Expand Down
1 change: 0 additions & 1 deletion src/ReactiveUI.Winforms/Registrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public void Register(IRegistrar registrar)
if (!ModeDetector.InUnitTestRunner())
{
WindowsFormsSynchronizationContext.AutoInstall = true;
RxSchedulers.MainThreadScheduler = new WaitForDispatcherScheduler(static () => new SynchronizationContextScheduler(new WindowsFormsSynchronizationContext()));
}
}
}
3 changes: 2 additions & 1 deletion src/ReactiveUI.Wpf/Builder/WpfReactiveUIBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public static IReactiveUIBuilder WithWpf(this IReactiveUIBuilder builder)
return builder
.WithPlatformModule<Wpf.Registrations>()
.WithPlatformServices()
.WithWpfScheduler();
.WithWpfScheduler()
.WithTaskPoolScheduler(TaskPoolScheduler.Default);
}

/// <summary>
Expand Down
7 changes: 0 additions & 7 deletions src/ReactiveUI.Wpf/Registrations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,6 @@ public void Register(IRegistrar registrar)
registrar.RegisterConstant<IPropertyBindingHook>(static () => new AutoDataTemplateBindingHook());
registrar.RegisterConstant<IBindingFallbackConverter>(static () => new ComponentModelFallbackConverter());

if (!ModeDetector.InUnitTestRunner())
{
// NB: On .NET Core, trying to touch DispatcherScheduler blows up :cry:
RxSchedulers.MainThreadScheduler = new WaitForDispatcherScheduler(static () => DispatcherScheduler.Current);
RxSchedulers.TaskpoolScheduler = TaskPoolScheduler.Default;
}

RxSchedulers.SuppressViewCommandBindingMessage = true;
}
}
20 changes: 19 additions & 1 deletion src/ReactiveUI/Builder/IReactiveUIBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,18 @@ namespace ReactiveUI.Builder;
/// <seealso cref="IAppBuilder" />
public interface IReactiveUIBuilder : IAppBuilder
{
/// <summary>
/// Configures the message bus.
/// </summary>
/// <returns>The builder instance for chaining.</returns>
IReactiveUIBuilder WithMessageBus();

/// <summary>
/// Configures the message bus.
/// </summary>
/// <param name="configure">A delegate to configure the message bus.</param>
/// <returns>The builder instance for chaining.</returns>
IReactiveUIBuilder ConfigureMessageBus(Action<MessageBus> configure);
IReactiveUIBuilder WithMessageBus(Action<IMessageBus> configure);

/// <summary>
/// Registers a custom message bus instance.
Expand Down Expand Up @@ -121,6 +127,18 @@ IReactiveUIBuilder RegisterView<TView, TViewModel>()
IReactiveUIBuilder RegisterViewModel<TViewModel>()
where TViewModel : class, IReactiveObject, new();

/// <summary>
/// Registers a constant instance of the specified view model type for use in the reactive UI builder.
/// </summary>
/// <remarks>The registered view model instance is created once using its parameterless constructor and
/// reused for all requests. Use this method when the view model does not require per-request state or
/// dependencies.</remarks>
/// <typeparam name="TViewModel">The type of the view model to register. Must be a reference type that implements IReactiveObject and has a
/// parameterless constructor.</typeparam>
/// <returns>The current instance of the reactive UI builder, enabling method chaining.</returns>
IReactiveUIBuilder RegisterConstantViewModel<TViewModel>()
where TViewModel : class, IReactiveObject, new();

/// <summary>
/// Withes the main thread scheduler.
/// </summary>
Expand Down
36 changes: 29 additions & 7 deletions src/ReactiveUI/Builder/ReactiveUIBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,19 +272,29 @@ public IReactiveUIBuilder ForPlatforms(params Action<IReactiveUIBuilder>[] platf
return this;
}

/// <summary>
/// Configures the ReactiveUI message bus.
/// </summary>
/// <returns>The builder instance for chaining.</returns>
public IReactiveUIBuilder WithMessageBus() =>
WithRegistrationOnBuild(resolver =>
{
_messageBus = new MessageBus();
resolver.RegisterConstant<IMessageBus>(_messageBus);
});

/// <summary>
/// Configures the ReactiveUI message bus.
/// </summary>
/// <param name="configure">The configuration action.</param>
/// <returns>The builder instance for chaining.</returns>
public IReactiveUIBuilder ConfigureMessageBus(Action<MessageBus> configure) =>
public IReactiveUIBuilder WithMessageBus(Action<IMessageBus> configure) =>
WithRegistrationOnBuild(resolver =>
resolver.Register<IMessageBus>(() =>
{
var messageBus = new MessageBus();
configure(messageBus);
return messageBus;
}));
{
_messageBus = new MessageBus();
configure(_messageBus);
resolver.RegisterConstant<IMessageBus>(_messageBus);
});

/// <summary>
/// Registers a custom message bus instance.
Expand Down Expand Up @@ -632,6 +642,18 @@ public IReactiveUIBuilder RegisterViewModel<TViewModel>()
where TViewModel : class, IReactiveObject, new() =>
WithRegistration(static resolver => resolver.Register<TViewModel>(static () => new()));

/// <summary>
/// Registers a constant instance of the specified view model type in the dependency resolver.
/// </summary>
/// <remarks>This method creates a single instance of the specified view model type and registers it as a
/// constant in the resolver. All requests for this view model type will return the same instance.</remarks>
/// <typeparam name="TViewModel">The type of the view model to register. Must be a class that implements IReactiveObject and has a parameterless
/// constructor.</typeparam>
/// <returns>The current builder instance, enabling further configuration of the dependency resolver.</returns>
public IReactiveUIBuilder RegisterConstantViewModel<TViewModel>()
where TViewModel : class, IReactiveObject, new() =>
WithRegistration(static resolver => resolver.RegisterConstant(new TViewModel()));

/// <summary>
/// Registers a custom view model with the dependency resolver.
/// </summary>
Expand Down
36 changes: 34 additions & 2 deletions src/ReactiveUI/Mixins/BuilderMixins.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,22 @@ public static IReactiveUIBuilder ForPlatforms(this IReactiveUIBuilder reactiveUI
return reactiveUIBuilder;
}

/// <summary>
/// Configures the ReactiveUI message bus.
/// </summary>
/// <param name="reactiveUIBuilder">The reactive UI builder.</param>
/// <returns>
/// The builder instance for chaining.
/// </returns>
/// <exception cref="ArgumentNullException">reactiveUIBuilder.</exception>
public static IReactiveUIBuilder WithMessageBus(this IReactiveUIBuilder reactiveUIBuilder)
{
ArgumentExceptionHelper.ThrowIfNull(reactiveUIBuilder);

reactiveUIBuilder.WithMessageBus();
return reactiveUIBuilder;
}

/// <summary>
/// Configures the ReactiveUI message bus.
/// </summary>
Expand All @@ -315,11 +331,11 @@ public static IReactiveUIBuilder ForPlatforms(this IReactiveUIBuilder reactiveUI
/// The builder instance for chaining.
/// </returns>
/// <exception cref="ArgumentNullException">reactiveUIBuilder.</exception>
public static IReactiveUIBuilder ConfigureMessageBus(this IReactiveUIBuilder reactiveUIBuilder, Action<MessageBus> configure)
public static IReactiveUIBuilder WithMessageBus(this IReactiveUIBuilder reactiveUIBuilder, Action<IMessageBus> configure)
{
ArgumentExceptionHelper.ThrowIfNull(reactiveUIBuilder);

reactiveUIBuilder.ConfigureMessageBus(configure);
reactiveUIBuilder.WithMessageBus(configure);
return reactiveUIBuilder;
}

Expand Down Expand Up @@ -392,6 +408,22 @@ public static IReactiveUIBuilder RegisterViewModel<TViewModel>(this IReactiveUIB
return reactiveUIBuilder;
}

/// <summary>
/// Registers a constant instance of the specified view model type for use with the ReactiveUI builder.
/// </summary>
/// <typeparam name="TViewModel">The type of the view model to register. Must be a class that implements IReactiveObject and has a parameterless
/// constructor.</typeparam>
/// <param name="reactiveUIBuilder">The ReactiveUI builder to configure. Cannot be null.</param>
/// <returns>The same ReactiveUI builder instance, to allow for method chaining.</returns>
public static IReactiveUIBuilder RegisterConstantViewModel<TViewModel>(this IReactiveUIBuilder reactiveUIBuilder)
where TViewModel : class, IReactiveObject, new()
{
ArgumentExceptionHelper.ThrowIfNull(reactiveUIBuilder);

reactiveUIBuilder.RegisterConstantViewModel<TViewModel>();
return reactiveUIBuilder;
}

/// <summary>
/// Registers a custom view model with the dependency resolver.
/// </summary>
Expand Down
10 changes: 1 addition & 9 deletions src/examples/ReactiveUI.Builder.BlazorServer/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
using ReactiveUI.Builder.BlazorServer.Components;
using ReactiveUI.Builder.BlazorServer.Services;
using ReactiveUI.Builder.BlazorServer.ViewModels;
using ReactiveUI.Builder.BlazorServer.Views;
using Splat;
using Splat.Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);
Expand All @@ -30,14 +28,8 @@

RxAppBuilder.CreateReactiveUIBuilder()
.WithBlazor()
.WithMessageBus()
.WithViewsFromAssembly(typeof(Program).Assembly)
.WithRegistration(locator =>
{
if (Locator.Current.GetService<IMessageBus>() is null)
{
locator.RegisterConstant(MessageBus.Current);
}
})
.BuildApp();

var app = builder.Build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
<DefaultPackageDescription>Blazor Server example app for ReactiveUI Builder.</DefaultPackageDescription>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System.IO;
using System.Reactive;
using System.Reactive.Linq;
using System.Text.Json;
Expand Down Expand Up @@ -70,7 +69,7 @@ public IObservable<Unit> InvalidateState() => Observable.Start(
{
if (!File.Exists(path))
{
return default(T);
return default;
}

var json = File.ReadAllText(path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

using System.Diagnostics;
using System.Reactive.Linq;
using Microsoft.Extensions.Hosting;
using ReactiveUI;
using ReactiveUI.Builder.BlazorServer.Models;
using Splat;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

using System.Reactive.Linq;
using Microsoft.AspNetCore.Components.Web;
using ReactiveUI;
using ReactiveUI.Blazor;
using ReactiveUI.Builder.BlazorServer.Models;
using ReactiveUI.Builder.BlazorServer.ViewModels;
Expand Down
9 changes: 2 additions & 7 deletions src/examples/ReactiveUI.Builder.WpfApp/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected override void OnStartup(StartupEventArgs e)
base.OnStartup(e);

// Initialize ReactiveUI via the Builder only
RxAppBuilder.CreateReactiveUIBuilder()
var app = RxAppBuilder.CreateReactiveUIBuilder()
.WithWpf()
.WithViewsFromAssembly(typeof(App).Assembly) // auto-register all IViewFor in this assembly
////.RegisterView<MainWindow, ViewModels.AppBootstrapper>()
Expand All @@ -52,17 +52,12 @@ protected override void OnStartup(StartupEventArgs e)
Debugger.Break();
}
}))
.WithMessageBus()
.WithRegistration(static r =>
{
// Register IScreen as a singleton so all resolutions share the same Router
r.RegisterLazySingleton<IScreen>(static () => new ViewModels.AppBootstrapper());

// Register MessageBus as a singleton if not already
if (Locator.Current.GetService<IMessageBus>() is null)
{
r.RegisterConstant(MessageBus.Current);
}

// Cross-process instance lifetime coordination
r.RegisterLazySingleton(static () => new Services.AppLifetimeCoordinator());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

namespace ReactiveUI.Builder.WpfApp.Services;
using ReactiveUI.Builder.WpfApp.Services;

namespace ReactiveUI.Builder.WpfApp.Models;

/// <summary>
/// Network event describing a change in the rooms list.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@

<ItemGroup>
<Using Include="ReactiveUI.Helpers" />
<Using Include="System.Collections.ObjectModel" />
<Using Include="System.IO.MemoryMappedFiles" />
<Using Include="System.Diagnostics" />
<Using Include="System.Net" />
<Using Include="System.Net.Sockets" />
<Using Include="System.Reactive" />
<Using Include="System.Reactive.Linq" />
<Using Include="System.Text.Json" />
</ItemGroup>

</Project>
Loading
Loading