From ca60609f829db788329c094e8780cedacbb7e5cb Mon Sep 17 00:00:00 2001 From: Matthias Bruzek Date: Tue, 1 Jun 2021 19:57:30 +0200 Subject: [PATCH 1/4] fix: Change access modifier for SubscribePropertyChangedEvents to public - this change enables consumers to implement IReactiveObject and get PropertyChanged and PropertyChanging notifications (which regressed in version 11.4.1) - to get the notifications, one must call this.SubscribePropertyChangedEvents() or this.SubscribePropertyChangingEvents() on the IReactiveObject instance - related: #2594 --- ...provalTests.ReactiveUI.net472.approved.txt | 6 ++- ...provalTests.ReactiveUI.net5.0.approved.txt | 6 ++- ...ests.ReactiveUI.netcoreapp3.1.approved.txt | 6 ++- .../IReactiveObjectExtensions.cs | 44 ++++++++++++------- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt index 9f4af14a9e..15a22f4076 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt @@ -300,6 +300,10 @@ namespace ReactiveUI where TSender : ReactiveUI.IReactiveObject { } public static void RaisePropertyChanging(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TSender : ReactiveUI.IReactiveObject { } + public static void SubscribePropertyChangedEvents(this TSender reactiveObject) + where TSender : ReactiveUI.IReactiveObject { } + public static void SubscribePropertyChangingEvents(this TSender reactiveObject) + where TSender : ReactiveUI.IReactiveObject { } } public interface IReactivePropertyChangedEventArgs { @@ -931,4 +935,4 @@ namespace System.Reactive.Disposables public static T DisposeWith(this T item, System.Reactive.Disposables.CompositeDisposable compositeDisposable) where T : System.IDisposable { } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt index f0f88b0dab..884ee41680 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt @@ -295,6 +295,10 @@ namespace ReactiveUI where TSender : ReactiveUI.IReactiveObject { } public static void RaisePropertyChanging(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TSender : ReactiveUI.IReactiveObject { } + public static void SubscribePropertyChangedEvents(this TSender reactiveObject) + where TSender : ReactiveUI.IReactiveObject { } + public static void SubscribePropertyChangingEvents(this TSender reactiveObject) + where TSender : ReactiveUI.IReactiveObject { } } public interface IReactivePropertyChangedEventArgs { @@ -926,4 +930,4 @@ namespace System.Reactive.Disposables public static T DisposeWith(this T item, System.Reactive.Disposables.CompositeDisposable compositeDisposable) where T : System.IDisposable { } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt index 7a858719b5..6f6a58d8fa 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt @@ -293,6 +293,10 @@ namespace ReactiveUI where TSender : ReactiveUI.IReactiveObject { } public static void RaisePropertyChanging(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TSender : ReactiveUI.IReactiveObject { } + public static void SubscribePropertyChangedEvents(this TSender reactiveObject) + where TSender : ReactiveUI.IReactiveObject { } + public static void SubscribePropertyChangingEvents(this TSender reactiveObject) + where TSender : ReactiveUI.IReactiveObject { } } public interface IReactivePropertyChangedEventArgs { @@ -924,4 +928,4 @@ namespace System.Reactive.Disposables public static T DisposeWith(this T item, System.Reactive.Disposables.CompositeDisposable compositeDisposable) where T : System.IDisposable { } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs b/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs index ca33ae1fe5..4cef832fb8 100644 --- a/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs +++ b/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs @@ -170,6 +170,34 @@ public static void RaisePropertyChanging(this TSender reactiveObject, [ } } + /// + /// Use this method for enabling classic PropertyChanging events when you + /// are implementing IReactiveObject manually. + /// + /// The sender type. + /// The instance of IReactiveObject which should propagate property changes. + public static void SubscribePropertyChangingEvents(this TSender reactiveObject) + where TSender : IReactiveObject + { + var s = state.GetValue(reactiveObject, _ => (IExtensionState)new ExtensionState(reactiveObject)); + + s.SubscribePropertyChangingEvents(); + } + + /// + /// Use this method for enabling classic PropertyChanged events when you + /// are implementing IReactiveObject manually. + /// + /// The sender type. + /// The instance of IReactiveObject which should propagate property changes. + public static void SubscribePropertyChangedEvents(this TSender reactiveObject) + where TSender : IReactiveObject + { + var s = state.GetValue(reactiveObject, _ => (IExtensionState)new ExtensionState(reactiveObject)); + + s.SubscribePropertyChangedEvents(); + } + internal static IObservable> GetChangedObservable(this TSender reactiveObject) where TSender : IReactiveObject { @@ -191,14 +219,6 @@ internal static IObservable GetThrownExceptionsObservable(th return s.ThrownExceptions; } - internal static void SubscribePropertyChangingEvents(this TSender reactiveObject) - where TSender : IReactiveObject - { - var s = state.GetValue(reactiveObject, _ => (IExtensionState)new ExtensionState(reactiveObject)); - - s.SubscribePropertyChangingEvents(); - } - internal static void RaisingPropertyChanging(this TSender reactiveObject, string propertyName) where TSender : IReactiveObject { @@ -212,14 +232,6 @@ internal static void RaisingPropertyChanging(this TSender reactiveObjec s.RaisePropertyChanging(propertyName); } - internal static void SubscribePropertyChangedEvents(this TSender reactiveObject) - where TSender : IReactiveObject - { - var s = state.GetValue(reactiveObject, _ => (IExtensionState)new ExtensionState(reactiveObject)); - - s.SubscribePropertyChangedEvents(); - } - internal static void RaisingPropertyChanged(this TSender reactiveObject, string propertyName) where TSender : IReactiveObject { From 492bf978693d3aa917735357a77c7f52ea2f90e4 Mon Sep 17 00:00:00 2001 From: Matthias Bruzek Date: Tue, 1 Jun 2021 19:57:39 +0200 Subject: [PATCH 2/4] fix: unit tests failing on Device with de_AT culture - there were unit tests failing because they compared string representations of double in the CultureInfo.InvariantCulture format. This was changed to CultureInfo.CurrentCulture to work with the culture of the Device running the tests --- .../Platforms/windows-xaml/PropertyBindingTest.cs | 4 ++-- .../Platforms/winforms/DefaultPropertyBindingTests.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs index 3b28e4a8be..0815bec3ae 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs @@ -114,10 +114,10 @@ public void TypeConvertedTwoWayBindSmokeTest() vm.JustADecimal = 17.2m; var disp1 = fixture.Bind(vm, view, x => x.JustADecimal, x => x.SomeTextBox.Text, (IObservable?)null, null); - Assert.Equal(vm.JustADecimal.ToString(CultureInfo.InvariantCulture), view.SomeTextBox.Text); + Assert.Equal(vm.JustADecimal.ToString(CultureInfo.CurrentCulture), view.SomeTextBox.Text); Assert.Equal(17.2m, vm.JustADecimal); - view.SomeTextBox.Text = 42.3m.ToString(CultureInfo.InvariantCulture); + view.SomeTextBox.Text = 42.3m.ToString(CultureInfo.CurrentCulture); Assert.Equal(42.3m, vm.JustADecimal); // Bad formatting. diff --git a/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs index 8aed8d1095..2024acdd85 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs @@ -143,7 +143,7 @@ public void CanBindViewModelToWinformControls() var disp2 = view.Bind(vm, x => x.SomeDouble, x => x.Property3.Text); vm.SomeDouble = 123.4; - Assert.Equal(vm.SomeDouble.ToString(CultureInfo.InvariantCulture), view.Property3.Text); + Assert.Equal(vm.SomeDouble.ToString(CultureInfo.CurrentCulture), view.Property3.Text); } /// From e6c507d510f1d5ca6d441db6ea460015147a85b1 Mon Sep 17 00:00:00 2001 From: Matthias Bruzek Date: Tue, 1 Jun 2021 20:12:07 +0200 Subject: [PATCH 3/4] fix: approval tests failing because of wrong parameter names --- .../API/ApiApprovalTests.ReactiveUI.net472.approved.txt | 4 ++-- .../API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt | 4 ++-- .../ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt index 15a22f4076..90089dcd68 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt @@ -662,8 +662,8 @@ namespace ReactiveUI protected virtual bool PrintMembers(System.Text.StringBuilder builder) { } public System.IDisposable SuppressChangeNotifications() { } public override string ToString() { } - public static bool operator !=(ReactiveUI.ReactiveRecord? r1, ReactiveUI.ReactiveRecord? r2) { } - public static bool operator ==(ReactiveUI.ReactiveRecord? r1, ReactiveUI.ReactiveRecord? r2) { } + public static bool operator !=(ReactiveUI.ReactiveRecord? left, ReactiveUI.ReactiveRecord? right) { } + public static bool operator ==(ReactiveUI.ReactiveRecord? left, ReactiveUI.ReactiveRecord? right) { } } public static class Reflection { diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt index 884ee41680..1c8ae13450 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net5.0.approved.txt @@ -657,8 +657,8 @@ namespace ReactiveUI protected virtual bool PrintMembers(System.Text.StringBuilder builder) { } public System.IDisposable SuppressChangeNotifications() { } public override string ToString() { } - public static bool operator !=(ReactiveUI.ReactiveRecord? r1, ReactiveUI.ReactiveRecord? r2) { } - public static bool operator ==(ReactiveUI.ReactiveRecord? r1, ReactiveUI.ReactiveRecord? r2) { } + public static bool operator !=(ReactiveUI.ReactiveRecord? left, ReactiveUI.ReactiveRecord? right) { } + public static bool operator ==(ReactiveUI.ReactiveRecord? left, ReactiveUI.ReactiveRecord? right) { } } public static class Reflection { diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt index 6f6a58d8fa..eb7f8699cd 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt @@ -655,8 +655,8 @@ namespace ReactiveUI protected virtual bool PrintMembers(System.Text.StringBuilder builder) { } public System.IDisposable SuppressChangeNotifications() { } public override string ToString() { } - public static bool operator !=(ReactiveUI.ReactiveRecord? r1, ReactiveUI.ReactiveRecord? r2) { } - public static bool operator ==(ReactiveUI.ReactiveRecord? r1, ReactiveUI.ReactiveRecord? r2) { } + public static bool operator !=(ReactiveUI.ReactiveRecord? left, ReactiveUI.ReactiveRecord? right) { } + public static bool operator ==(ReactiveUI.ReactiveRecord? left, ReactiveUI.ReactiveRecord? right) { } } public static class Reflection { From 95e4b0b475b5f4fd9c3f7a58a3351095ca338dcb Mon Sep 17 00:00:00 2001 From: Matthias Bruzek Date: Tue, 1 Jun 2021 20:16:05 +0200 Subject: [PATCH 4/4] fix: Approval tests fail after saving file which automatically adds blank line --- src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs b/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs index 08ae4ff50e..62b2b9e167 100644 --- a/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs +++ b/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs @@ -83,7 +83,7 @@ protected static void CheckApproval(Assembly assembly, [CallerMemberName]string? } } - Assert.Equal(approvedPublicApi, receivedPublicApi); + Assert.Equal(approvedPublicApi.Trim(), receivedPublicApi); } private static string Filter(string text)