Skip to content

Commit 219b20f

Browse files
authored
Refactor WhenAnyValue usage to generic overloads (#4097)
<!-- 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 --> Replaces lambda-based WhenAnyValue calls with explicit generic overloads across multiple platforms and components for improved AOT compatibility and clarity. Adds SuppressMessage attributes to registration classes to address trimming and AOT warnings where dynamic code or reflection is not always used. Also updates project file to suppress IL2026 and IL3050 warnings for AOT tests. **What might this PR break?** New feature, part of a larger breaking change **Please check if the PR fulfills these requirements** - [ ] Tests for the changes have been added (for bug fixes / features) - [ ] Docs have been added / updated (for bug fixes / features) **Other information**:
1 parent f8a8979 commit 219b20f

25 files changed

+38
-15
lines changed

src/ReactiveUI.AOTTests/ReactiveUI.AOT.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<PublishAot>true</PublishAot>
1010
<InvariantGlobalization>true</InvariantGlobalization>
1111
<TrimMode>full</TrimMode>
12+
<NoWarn>$(NoWarn);IL2026;IL3050;</NoWarn>
1213
</PropertyGroup>
1314

1415
<ItemGroup>

src/ReactiveUI.AOTTests/StringBasedObservationTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
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 System.Diagnostics.CodeAnalysis;
67
using System.Reactive.Concurrency;
78
using System.Reactive.Linq;
89

src/ReactiveUI.AndroidX/Registrations.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public class Registrations : IWantsToRegisterStuff
1717
#if NET6_0_OR_GREATER
1818
[RequiresDynamicCode("Register uses methods that require dynamic code generation")]
1919
[RequiresUnreferencedCode("Register uses methods that may require unreferenced code")]
20+
[SuppressMessage("Trimming", "IL2046:'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.", Justification = "Not all paths use reflection")]
21+
[SuppressMessage("AOT", "IL3051:'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.", Justification = "Not all paths use reflection")]
2022
#endif
2123
public void Register(Action<Func<object>, Type> registerFunction)
2224
{

src/ReactiveUI.Blazor/ReactiveComponentBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ protected override void OnAfterRender(bool firstRender)
9292
{
9393
// The following subscriptions are here because if they are done in OnInitialized, they conflict with certain JavaScript frameworks.
9494
var viewModelChanged =
95-
this.WhenAnyValue(x => x.ViewModel)
95+
this.WhenAnyValue<ReactiveComponentBase<T>, T?>(nameof(ViewModel))
9696
.WhereNotNull()
9797
.Publish()
9898
.RefCount(2);

src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected override void OnAfterRender(bool firstRender)
9494
{
9595
// The following subscriptions are here because if they are done in OnInitialized, they conflict with certain JavaScript frameworks.
9696
var viewModelChanged =
97-
this.WhenAnyValue(x => x.ViewModel)
97+
this.WhenAnyValue<ReactiveInjectableComponentBase<T>, T?>(nameof(ViewModel))
9898
.WhereNotNull()
9999
.Publish()
100100
.RefCount(2);

src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ protected override void OnAfterRender(bool isFirstRender)
9191
if (isFirstRender)
9292
{
9393
var viewModelChanged =
94-
this.WhenAnyValue(x => x.ViewModel)
94+
this.WhenAnyValue<ReactiveLayoutComponentBase<T>, T?>(nameof(ViewModel))
9595
.WhereNotNull()
9696
.Publish()
9797
.RefCount(2);

src/ReactiveUI.Blazor/Registrations.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public class Registrations : IWantsToRegisterStuff
1717
#if NET6_0_OR_GREATER
1818
[RequiresDynamicCode("Register uses methods that require dynamic code generation")]
1919
[RequiresUnreferencedCode("Register uses methods that may require unreferenced code")]
20+
[SuppressMessage("Trimming", "IL2046:'RequiresUnreferencedCodeAttribute' annotations must match across all interface implementations or overrides.", Justification = "Not all paths use reflection")]
21+
[SuppressMessage("AOT", "IL3051:'RequiresDynamicCodeAttribute' annotations must match across all interface implementations or overrides.", Justification = "Not all paths use reflection")]
2022
#endif
2123
public void Register(Action<Func<object>, Type> registerFunction)
2224
{

src/ReactiveUI.Builder.WpfApp/ViewModels/ChatRoomViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public ChatRoomViewModel(IScreen hostScreen, ChatRoom room, string user)
3333
_room = room;
3434
_user = user;
3535

36-
var canSend = this.WhenAnyValue(x => x.MessageText, txt => !string.IsNullOrWhiteSpace(txt));
36+
var canSend = this.WhenAnyValue<ChatRoomViewModel, bool, string>(nameof(MessageText), txt => !string.IsNullOrWhiteSpace(txt));
3737
SendMessage = ReactiveCommand.Create(SendMessageImpl, canSend);
3838

3939
// Observe new incoming messages via MessageBus using the room name as the contract across instances

src/ReactiveUI.Builder.WpfApp/ViewModels/LobbyViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public LobbyViewModel(IScreen hostScreen)
2929
HostScreen = hostScreen;
3030
UrlPathSegment = "lobby";
3131

32-
var canCreate = this.WhenAnyValue(x => x.RoomName, rn => !string.IsNullOrWhiteSpace(rn));
32+
var canCreate = this.WhenAnyValue<LobbyViewModel, bool, string>(nameof(RoomName), rn => !string.IsNullOrWhiteSpace(rn));
3333
CreateRoom = ReactiveCommand.Create(CreateRoomImpl, canCreate);
3434

3535
DeleteRoom = ReactiveCommand.Create<ChatRoom>(DeleteRoomImpl);

src/ReactiveUI.Builder.WpfApp/Views/ChatRoomView.xaml.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using System.Reactive.Disposables;
77
using System.Windows;
8+
using ReactiveUI.Builder.WpfApp.ViewModels;
89

910
namespace ReactiveUI.Builder.WpfApp.Views;
1011

@@ -28,7 +29,7 @@ public ChatRoomView()
2829
this.WhenActivated(d =>
2930
{
3031
// Map ViewModel to DataContext for XAML bindings like {Binding RoomName}
31-
this.WhenAnyValue(v => v.ViewModel).BindTo(this, v => v.DataContext).DisposeWith(d);
32+
this.WhenAnyValue<ChatRoomView, ChatRoomViewModel>(nameof(ViewModel)).BindTo(this, v => v.DataContext).DisposeWith(d);
3233

3334
this.Bind(ViewModel, vm => vm.MessageText, v => v.MessageBox.Text).DisposeWith(d);
3435
this.BindCommand(ViewModel, vm => vm.SendMessage, v => v.SendButton).DisposeWith(d);

0 commit comments

Comments
 (0)