diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2db0b0511..4cc362262 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,13 +10,14 @@ jobs: build: runs-on: windows-latest steps: - - name: 'Setup dotnet 6 / 7 / 8' - uses: actions/setup-dotnet@v5 + - name: Setup .NET (With cache) + uses: actions/setup-dotnet@v5.0.0 with: - dotnet-version: | - 6.0.x - 7.0.x - 8.0.x + dotnet-version: | + 8.0.x + 9.0.x + 10.0.x + dotnet-quality: 'preview' - name: 'Setup Java JDK 11' uses: actions/setup-java@v5.0.0 diff --git a/build/Build.cs b/build/Build.cs index 46e6adaef..c5270352d 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -26,7 +26,7 @@ class Build : NukeBuild private static readonly string splat = nameof(splat); private static readonly string DynamicData = nameof(DynamicData); private static readonly string reactivemarbles = nameof(reactivemarbles); - private static readonly string[] RxUIProjects = new string[] { reactiveui, akavache, fusillade, punchclock, splat, "ReactiveUI.Validation" }; + private static readonly string[] RxUIProjects = [reactiveui, akavache, fusillade, punchclock, splat, "ReactiveUI.Validation"]; private AbsolutePath RxUIAPIDirectory => RootDirectory / reactiveui / "api" / reactiveui; private AbsolutePath RxMAPIDirectory => RootDirectory / reactiveui / "api" / reactivemarbles; diff --git a/global.json b/global.json index 5cfa01d9c..33b94ff50 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,7 @@ { - "msbuild-sdks": { - "MSBuild.Sdk.Extras": "3.0.44" - } + "sdk": { + "version": "10.0.100-rc.2.25502.107", + "rollForward": "latestFeature", + "allowPrerelease": true + } } diff --git a/reactiveui/docs/handbook/index.md b/reactiveui/docs/handbook/index.md index dd02306b3..5b830a6a6 100644 --- a/reactiveui/docs/handbook/index.md +++ b/reactiveui/docs/handbook/index.md @@ -6,6 +6,7 @@ Order: 15 Welcome to the ReactiveUI Handbook. This section provides comprehensive documentation for using ReactiveUI with .NET 8 and the latest best practices. Explore the topics below to learn about core concepts, advanced features, platform-specific guidance, and related projects. ## Core Topics +- [RxAppBuilder](rxappbuilder.md) - [Commands](commands/index.md) - [Data Binding](data-binding/index.md) - [View Models](view-models/index.md) diff --git a/reactiveui/docs/handbook/rxappbuilder.md b/reactiveui/docs/handbook/rxappbuilder.md new file mode 100644 index 000000000..91224f0f8 --- /dev/null +++ b/reactiveui/docs/handbook/rxappbuilder.md @@ -0,0 +1,128 @@ +# RxAppBuilder in ReactiveUI - introduced in V21.0.1 + +The `RxAppBuilder` class in ReactiveUI is responsible for initializing and configuring the ReactiveUI framework within your application. +It provides a fluent API to set up various components and services that ReactiveUI relies on. +It extends the capabilities of the Splat Builder and Splat AppLocator to register platform-specific services, views, view models, and other dependencies required for ReactiveUI to function correctly. + +## Key Features of RxAppBuilder +- **Fluent Configuration**: The `RxAppBuilder` class allows you to chain configuration methods to set up your application in a readable and maintainable way. +- **Service Registration**: You can register services and dependencies that your application will use, such as view models, views, and other services. +- **Platform Integration**: It provides methods to integrate ReactiveUI with different platforms, ensuring that the framework works seamlessly across various environments. +- **Customization**: You can customize the behavior of ReactiveUI by configuring options and settings that suit your application's needs. +- **Initialization**: The `RxAppBuilder` class includes methods to initialize the ReactiveUI framework, ensuring that all necessary components are set up before your application starts. + +## Example Usage +```csharp +var rxuiInstance = RxAppBuilder.CreateReactiveUIBuilder() + .WithWpf() // Register WPF platform services + .WithViewsFromAssembly(typeof(App).Assembly) // Register views and view models + .WithRegistration(locator => + { + // Register IScreen as a singleton so all resolutions share the same Router + locator.RegisterLazySingleton(static () => new AppBootstrapper()); + }) + .BuildApp(); + +var mainUIThreadScheduler = rxuiInstance.MainThreadScheduler; +var taskpoolScheduler = rxuiInstance.TaskpoolScheduler; +``` + +## Platform Support +The `RxAppBuilder` class supports various platforms, including WPF, Xamarin.Forms, and others. You can use platform-specific methods to ensure that ReactiveUI is properly configured for the target environment. + +ReactiveUI.AndroidX - `WithAndroidX()` +ReactiveUI.WPF - `WithWpf()` +ReactiveUI.Maui - `WithMaui()` +ReactiveUI.Blazor - `WithBlazor()` +ReactiveUI.WinForms - `WithWinForms()` +ReactiveUI.WinUI - `WithWinUI()` + +## Registering Views and ViewModels +You can register views and view models from specific assemblies using the `WithViewsFromAssembly` method. This allows ReactiveUI to automatically discover and register your views and view models. +```csharp +.WithViewsFromAssembly(typeof(App).Assembly) +``` +You can also register individual views and view models using the `WithView` and `WithViewModel` methods. +```csharp +.RegisterView() +.RegisterSingletonView() +.RegisterViewModel() +.RegisterSingletonViewModel() +``` + +## Custom Service Registration +You can register custom services and dependencies using the `WithPlatformModule` method. This allows you to integrate your own platform-specific services into the ReactiveUI framework. Where T is a class that implements IWantsToRegisterStuff. +```csharp +.WithPlatformModule() +``` +## Configure Schedulers +You can configure the main thread and task pool schedulers used by ReactiveUI using the `WithMainThreadScheduler` and `WithTaskpoolScheduler` methods. +```csharp +.WithMainThreadScheduler(DispatcherScheduler.Current) +.WithTaskpoolScheduler(TaskPoolScheduler.Default) +``` + +The default scheduler extensions register the RxApp.MainThreadScheduler and RxApp.TaskpoolScheduler to use the appropriate schedulers for the platform. +This can be overridden by calling the above methods with `setRxApp = false` to prevent setting the RxApp static properties. + +```csharp +.WithMainThreadScheduler(DispatcherScheduler.Current, setRxApp: false) +.WithTaskpoolScheduler(TaskPoolScheduler.Default, setRxApp: false) +``` + +Each platform module also registers the appropriate default schedulers for that platform. +Custom schedulers can be provided as needed. +Each platform can be custom configured as needed. +By default the platform registers the appropriate `Schedulers` for that platform, the relevant `PlatformServices`, and the relevant `PlatformModule`. + +## Registration Options +The `RxAppBuilder` class provides various options for registering views, view models, and services. You can choose to register them as singletons or transient instances based on your application's requirements. + +One option is to use an immediate registration approach, where services are registered directly within the builder configuration. +```csharp +.WithRegistration(locator => +{ + // Register IScreen as a singleton so all resolutions share the same Router, this is applied immediately + locator.RegisterLazySingleton(static () => new AppBootstrapper()); +}) +``` +Another option is to use a deferred registration approach, where services are registered as the builder is built. +```csharp +.WithRegistrationOnBuild(locator => +{ + // Register IScreen as a singleton so all resolutions share the same Router, this is applied after BuildApp is called + locator.RegisterLazySingleton(static () => new AppBootstrapper()); +}) +``` + +## Using Splat Modules +You can also use Splat modules to register services and dependencies. This allows you to leverage existing Splat modules or create your own for better organization. +```csharp +.WithSplatModule(new MyCustomSplatModule()) +.WithSplatModule() +``` + +## Building the App +Once you have configured the `RxAppBuilder`, you can build the ReactiveUI application instance using the `BuildApp` method. This finalizes the configuration and prepares the application for use. +```csharp +var rxuiInstance = rxAppBuilder.BuildApp(); +var mainUIThreadScheduler = rxuiInstance.MainThreadScheduler; +var taskpoolScheduler = rxuiInstance.TaskpoolScheduler; +``` + +## WithInstance usage +This allows you to get instances from the underlying Splat service locator. +```csharp +rxuiInstance.WithInstance(screen => +{ // Use the registered IScreen instance for other services that depend on it. + screen.Router.Navigate.Execute(new MainViewModel(screen)); +}) +``` + +Up to 16 registered instances from Splat.AppLocator can be provided in a single WithInstance call. +```csharp +rxuiInstance.WithInstance((screen, dataService, logger) => +{ + // Use the registered instances for other services that depend on them. +}) +``` diff --git a/reactiveui/docs/handbook/toc.yml b/reactiveui/docs/handbook/toc.yml index c04d5f6d2..ecfe816bf 100644 --- a/reactiveui/docs/handbook/toc.yml +++ b/reactiveui/docs/handbook/toc.yml @@ -1,5 +1,7 @@ - name: Handbook href: index.md +- name: RxAppBuilder + href: rxappbuilder.md - name: Collections href: collections.md - name: Commands diff --git a/reactiveui/docs/handbook/view-models/boilerplate-code.md b/reactiveui/docs/handbook/view-models/boilerplate-code.md index f2eeef8cd..a29e93b53 100644 --- a/reactiveui/docs/handbook/view-models/boilerplate-code.md +++ b/reactiveui/docs/handbook/view-models/boilerplate-code.md @@ -1,5 +1,6 @@ # Source Generators and Fody, the easy way to create properties in ReactiveUI +## Legacy Note If you are tired of writing boilerplate code for property change notifications, you can try one of the following: - [PropertyChanged.Fody](https://github.com/Fody/PropertyChanged) or - [ReactiveUI.Fody](https://www.nuget.org/packages/ReactiveUI.Fody). @@ -7,6 +8,7 @@ If you are tired of writing boilerplate code for property change notifications, These two libraries are both based on [Fody](https://github.com/Fody) - an extensible tool for weaving .NET assemblies, and they'll inject `INotifyPropertyChanged` code into decorated properties at compile time for you. +## Recommend for new projects - [ReactiveUI.SourceGenerators](https://www.nuget.org/packages/ReactiveUI.SourceGenerators/) This library is a Source Generator that generates properties and commands for you. It is a new way to generate properties and commands for ReactiveUI taking decorated fields and methods and generating the properties and ReactiveCommands for you. @@ -499,7 +501,7 @@ using ReactiveUI.SourceGenerators.WinForms; public partial class MyCustomViewModelControlHost; ``` -# Using ReactiveUI.Fody +# Using ReactiveUI.Fody - Legacy With [ReactiveUI.Fody](https://www.nuget.org/packages/ReactiveUI.Fody/), you don't have to write boilerplate code for getters and setters of read-write properties — the package will do it automagically for you at compile time. All you have to do is annotate the property with the `[Reactive]` attribute, as shown below.