diff --git a/.gitignore b/.gitignore index 69c515f909..7965ec9224 100644 --- a/.gitignore +++ b/.gitignore @@ -365,4 +365,5 @@ src/Tools/ **/*.Android/**/[Rr]esource.[Dd]esigner.cs **/*.Droid/**/[Rr]esource.[Dd]esigner.cs **/Android/**/[Rr]esource.[Dd]esigner.cs -**/Droid/**/[Rr]esource.[Dd]esigner.cs \ No newline at end of file +**/Droid/**/[Rr]esource.[Dd]esigner.cs +**/[Rr]esources/[Rr]esource.[Dd]esigner.cs \ No newline at end of file diff --git a/src/Directory.build.props b/src/Directory.build.props index 63a443a800..2f1a8435d6 100644 --- a/src/Directory.build.props +++ b/src/Directory.build.props @@ -29,6 +29,9 @@ true $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + enable + latest + CS8600;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8623;CS8624;CS8625;CS8626;CS8627;CS8628;CS8629;CS8630;CS8634;CS8766;CS8767 diff --git a/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs b/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs index 0dfdf0580a..431b8f6848 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveAppCompatActivity.cs @@ -27,7 +27,7 @@ namespace ReactiveUI.AndroidSupport public class ReactiveAppCompatActivity : ReactiveAppCompatActivity, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -37,17 +37,17 @@ protected ReactiveAppCompatActivity() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -80,10 +80,10 @@ protected ReactiveAppCompatActivity(IntPtr handle, JniHandleOwnership ownership) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs b/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs index 800b5c08a0..426cefe9c1 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveDialogFragment.cs @@ -21,7 +21,7 @@ namespace ReactiveUI.AndroidSupport public class ReactiveDialogFragment : ReactiveDialogFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -31,17 +31,17 @@ protected ReactiveDialogFragment() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -63,10 +63,10 @@ protected ReactiveDialogFragment() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); diff --git a/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs b/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs index f06525cd0b..c5c0a392ca 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveFragment.cs @@ -21,7 +21,7 @@ namespace ReactiveUI.AndroidSupport public class ReactiveFragment : ReactiveFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -31,17 +31,17 @@ protected ReactiveFragment() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -63,10 +63,10 @@ protected ReactiveFragment() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); diff --git a/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs b/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs index 0bfdf52464..c8d3f8af1b 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveFragmentActivity.cs @@ -27,7 +27,7 @@ namespace ReactiveUI.AndroidSupport public class ReactiveFragmentActivity : ReactiveFragmentActivity, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -37,17 +37,17 @@ protected ReactiveFragmentActivity() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -63,10 +63,10 @@ public class ReactiveFragmentActivity : FragmentActivity, IReactiveObject, IReac private readonly Subject<(int requestCode, Result result, Intent intent)> _activityResult = new Subject<(int requestCode, Result result, Intent intent)>(); /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -78,7 +78,7 @@ public class ReactiveFragmentActivity : FragmentActivity, IReactiveObject, IReac public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); /// - /// Gets a singal when the activity fragment is activated. + /// Gets a signal when the activity fragment is activated. /// public IObservable Activated => _activated.AsObservable(); diff --git a/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs b/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs index f0a1326491..b2178f0c6d 100644 --- a/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs +++ b/src/ReactiveUI.AndroidSupport/ReactivePagerAdapter.cs @@ -28,7 +28,7 @@ public class ReactivePagerAdapter : PagerAdapter, IEnableLogger { private readonly SourceList _list; private readonly Func _viewCreator; - private readonly Action _viewInitializer; + private readonly Action? _viewInitializer; private readonly IDisposable _inner; /// @@ -40,7 +40,7 @@ public class ReactivePagerAdapter : PagerAdapter, IEnableLogger public ReactivePagerAdapter( IObservable> changeSet, Func viewCreator, - Action viewInitializer = null) + Action? viewInitializer = null) { _list = new SourceList(changeSet); _viewCreator = viewCreator; @@ -132,7 +132,7 @@ public class ReactivePagerAdapter : ReactivePagerAdapte public ReactivePagerAdapter( TCollection collection, Func viewCreator, - Action viewInitializer = null) + Action? viewInitializer = null) : base(collection.ToObservableChangeSet(), viewCreator, viewInitializer) { } diff --git a/src/ReactiveUI.AndroidSupport/ReactivePreferenceFragment.cs b/src/ReactiveUI.AndroidSupport/ReactivePreferenceFragment.cs index 987c5d2f24..b8c7b18b8d 100644 --- a/src/ReactiveUI.AndroidSupport/ReactivePreferenceFragment.cs +++ b/src/ReactiveUI.AndroidSupport/ReactivePreferenceFragment.cs @@ -23,7 +23,7 @@ namespace ReactiveUI.AndroidSupport public abstract class ReactivePreferenceFragment : ReactivePreferenceFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -43,17 +43,17 @@ protected ReactivePreferenceFragment(IntPtr handle, JniHandleOwnership ownership } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -85,10 +85,10 @@ protected ReactivePreferenceFragment(IntPtr handle, JniHandleOwnership ownership } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs index e8c4e20bef..29e84d2cc2 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewAdapter.cs @@ -60,7 +60,7 @@ public override int GetItemViewType(int position) /// The position of the current view in the list. /// The ViewModel associated with the current View. /// An ID to be used in OnCreateViewHolder. - public virtual int GetItemViewType(int position, TViewModel viewModel) + public virtual int GetItemViewType(int position, TViewModel? viewModel) { return base.GetItemViewType(position); } @@ -93,7 +93,7 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } - private TViewModel GetViewModelByPosition(int position) + private TViewModel? GetViewModelByPosition(int position) { return position >= _list.Count ? null : _list.Items.ElementAt(position); } diff --git a/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs index b984e447bb..cd03d10690 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs +++ b/src/ReactiveUI.AndroidSupport/ReactiveRecyclerViewViewHolder.cs @@ -29,9 +29,9 @@ public class ReactiveRecyclerViewViewHolder : RecyclerView.ViewHolde [SuppressMessage("Design", "CA1051: Do not declare visible instance fields", Justification = "Legacy reasons")] [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1306: Field should start with a lower case letter", Justification = "Legacy reasons")] [IgnoreDataMember] - protected Lazy AllPublicProperties; + protected Lazy AllPublicProperties = null!; - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -60,7 +60,7 @@ protected ReactiveRecyclerViewViewHolder(View view) h => view.LongClick += h, h => view.LongClick -= h); - SelectedWithViewModel = Observable.FromEvent( + SelectedWithViewModel = Observable.FromEvent( eventHandler => { void Handler(object sender, EventArgs e) => eventHandler(ViewModel); @@ -69,7 +69,7 @@ protected ReactiveRecyclerViewViewHolder(View view) h => view.Click += h, h => view.Click -= h); - LongClickedWithViewModel = Observable.FromEvent, TViewModel>( + LongClickedWithViewModel = Observable.FromEvent, TViewModel?>( eventHandler => { void Handler(object sender, View.LongClickEventArgs e) => eventHandler(ViewModel); @@ -80,10 +80,10 @@ protected ReactiveRecyclerViewViewHolder(View view) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler PropertyChanging = null!; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler PropertyChanged = null!; /// /// Gets an observable that signals that this ViewHolder has been selected. @@ -98,7 +98,7 @@ protected ReactiveRecyclerViewViewHolder(View view) /// /// The is the ViewModel of this ViewHolder in the . /// - public IObservable SelectedWithViewModel { get; } + public IObservable SelectedWithViewModel { get; } /// /// Gets an observable that signals that this ViewHolder has been long-clicked. @@ -113,7 +113,7 @@ protected ReactiveRecyclerViewViewHolder(View view) /// /// The is the ViewModel of this ViewHolder in the . /// - public IObservable LongClickedWithViewModel { get; } + public IObservable LongClickedWithViewModel { get; } /// /// Gets the current view being shown. @@ -121,7 +121,7 @@ protected ReactiveRecyclerViewViewHolder(View view) public View View => ItemView; /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); @@ -134,10 +134,10 @@ public TViewModel ViewModel public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj b/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj index 4a7f6ab8ae..2218e7bdcb 100644 --- a/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj +++ b/src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj @@ -4,6 +4,7 @@ MonoAndroid90 Provides ReactiveUI extensions for the Android Support Library ReactiveUI.AndroidSupport + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;xamarin;android;forms;monodroid;monotouch;xamarin.android;net; diff --git a/src/ReactiveUI.AndroidX/ReactiveAppCompatActivity.cs b/src/ReactiveUI.AndroidX/ReactiveAppCompatActivity.cs index 7097e67686..c199aa22ff 100644 --- a/src/ReactiveUI.AndroidX/ReactiveAppCompatActivity.cs +++ b/src/ReactiveUI.AndroidX/ReactiveAppCompatActivity.cs @@ -27,7 +27,7 @@ namespace ReactiveUI.AndroidX public class ReactiveAppCompatActivity : ReactiveAppCompatActivity, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -37,17 +37,17 @@ protected ReactiveAppCompatActivity() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -80,10 +80,10 @@ protected ReactiveAppCompatActivity(IntPtr handle, JniHandleOwnership ownership) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI.AndroidX/ReactiveDialogFragment.cs b/src/ReactiveUI.AndroidX/ReactiveDialogFragment.cs index cedf0dd587..88d9b7ec8e 100644 --- a/src/ReactiveUI.AndroidX/ReactiveDialogFragment.cs +++ b/src/ReactiveUI.AndroidX/ReactiveDialogFragment.cs @@ -21,7 +21,7 @@ namespace ReactiveUI.AndroidX public class ReactiveDialogFragment : ReactiveDialogFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -31,17 +31,17 @@ protected ReactiveDialogFragment() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -63,10 +63,10 @@ protected ReactiveDialogFragment() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); diff --git a/src/ReactiveUI.AndroidX/ReactiveFragment.cs b/src/ReactiveUI.AndroidX/ReactiveFragment.cs index 10dceded19..739de2b6b3 100644 --- a/src/ReactiveUI.AndroidX/ReactiveFragment.cs +++ b/src/ReactiveUI.AndroidX/ReactiveFragment.cs @@ -21,7 +21,7 @@ namespace ReactiveUI.AndroidX public class ReactiveFragment : ReactiveFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -31,17 +31,17 @@ protected ReactiveFragment() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -63,10 +63,10 @@ protected ReactiveFragment() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); diff --git a/src/ReactiveUI.AndroidX/ReactiveFragmentActivity.cs b/src/ReactiveUI.AndroidX/ReactiveFragmentActivity.cs index 5b0adb2e0a..cbd1bab194 100644 --- a/src/ReactiveUI.AndroidX/ReactiveFragmentActivity.cs +++ b/src/ReactiveUI.AndroidX/ReactiveFragmentActivity.cs @@ -26,7 +26,7 @@ namespace ReactiveUI.AndroidX public class ReactiveFragmentActivity : ReactiveFragmentActivity, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -36,17 +36,17 @@ protected ReactiveFragmentActivity() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -62,10 +62,10 @@ public class ReactiveFragmentActivity : FragmentActivity, IReactiveObject, IReac private readonly Subject<(int requestCode, Result result, Intent intent)> _activityResult = new Subject<(int requestCode, Result result, Intent intent)>(); /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI.AndroidX/ReactivePagerAdapter.cs b/src/ReactiveUI.AndroidX/ReactivePagerAdapter.cs index 9b554daf9e..e6186c1cf1 100644 --- a/src/ReactiveUI.AndroidX/ReactivePagerAdapter.cs +++ b/src/ReactiveUI.AndroidX/ReactivePagerAdapter.cs @@ -28,7 +28,7 @@ public class ReactivePagerAdapter : PagerAdapter, IEnableLogger { private readonly SourceList _list; private readonly Func _viewCreator; - private readonly Action _viewInitializer; + private readonly Action? _viewInitializer; private readonly IDisposable _inner; /// @@ -40,7 +40,7 @@ public class ReactivePagerAdapter : PagerAdapter, IEnableLogger public ReactivePagerAdapter( IObservable> changeSet, Func viewCreator, - Action viewInitializer = null) + Action? viewInitializer = null) { _list = new SourceList(changeSet); _viewCreator = viewCreator; @@ -132,7 +132,7 @@ public class ReactivePagerAdapter : ReactivePagerAdapte public ReactivePagerAdapter( TCollection collection, Func viewCreator, - Action viewInitializer = null) + Action? viewInitializer = null) : base(collection.ToObservableChangeSet(), viewCreator, viewInitializer) { } diff --git a/src/ReactiveUI.AndroidX/ReactivePreferenceFragment.cs b/src/ReactiveUI.AndroidX/ReactivePreferenceFragment.cs index 051fcd7b2d..db09c77c44 100644 --- a/src/ReactiveUI.AndroidX/ReactivePreferenceFragment.cs +++ b/src/ReactiveUI.AndroidX/ReactivePreferenceFragment.cs @@ -23,7 +23,7 @@ namespace ReactiveUI.AndroidX public abstract class ReactivePreferenceFragment : ReactivePreferenceFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -43,17 +43,17 @@ protected ReactivePreferenceFragment(IntPtr handle, JniHandleOwnership ownership } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value; } } @@ -85,10 +85,10 @@ protected ReactivePreferenceFragment(IntPtr handle, JniHandleOwnership ownership } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI.AndroidX/ReactiveRecyclerViewAdapter.cs b/src/ReactiveUI.AndroidX/ReactiveRecyclerViewAdapter.cs index da7064785f..52e01e60f9 100644 --- a/src/ReactiveUI.AndroidX/ReactiveRecyclerViewAdapter.cs +++ b/src/ReactiveUI.AndroidX/ReactiveRecyclerViewAdapter.cs @@ -56,7 +56,7 @@ public override int GetItemViewType(int position) /// The position of the current view in the list. /// The ViewModel associated with the current View. /// An ID to be used in OnCreateViewHolder. - public virtual int GetItemViewType(int position, TViewModel viewModel) + public virtual int GetItemViewType(int position, TViewModel? viewModel) { return base.GetItemViewType(position); } @@ -89,7 +89,7 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } - private TViewModel GetViewModelByPosition(int position) + private TViewModel? GetViewModelByPosition(int position) { return position >= _list.Count ? null : _list.Items.ElementAt(position); } diff --git a/src/ReactiveUI.AndroidX/ReactiveRecyclerViewViewHolder.cs b/src/ReactiveUI.AndroidX/ReactiveRecyclerViewViewHolder.cs index 5841a86718..1d2f604aa8 100644 --- a/src/ReactiveUI.AndroidX/ReactiveRecyclerViewViewHolder.cs +++ b/src/ReactiveUI.AndroidX/ReactiveRecyclerViewViewHolder.cs @@ -29,9 +29,9 @@ public class ReactiveRecyclerViewViewHolder : RecyclerView.ViewHolde [SuppressMessage("Design", "CA1051: Do not declare visible instance fields", Justification = "Legacy reasons")] [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1306: Field should start with a lower case letter", Justification = "Legacy reasons")] [IgnoreDataMember] - protected Lazy AllPublicProperties; + protected Lazy? AllPublicProperties; - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -60,7 +60,7 @@ protected ReactiveRecyclerViewViewHolder(View view) h => view.LongClick += h, h => view.LongClick -= h); - SelectedWithViewModel = Observable.FromEvent( + SelectedWithViewModel = Observable.FromEvent( eventHandler => { void Handler(object sender, EventArgs e) => eventHandler(ViewModel); @@ -69,7 +69,7 @@ protected ReactiveRecyclerViewViewHolder(View view) h => view.Click += h, h => view.Click -= h); - LongClickedWithViewModel = Observable.FromEvent, TViewModel>( + LongClickedWithViewModel = Observable.FromEvent, TViewModel?>( eventHandler => { void Handler(object sender, View.LongClickEventArgs e) => eventHandler(ViewModel); @@ -80,10 +80,10 @@ protected ReactiveRecyclerViewViewHolder(View view) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// /// Gets an observable that signals that this ViewHolder has been selected. @@ -98,7 +98,7 @@ protected ReactiveRecyclerViewViewHolder(View view) /// /// The is the ViewModel of this ViewHolder in the . /// - public IObservable SelectedWithViewModel { get; } + public IObservable SelectedWithViewModel { get; } /// /// Gets an observable that signals that this ViewHolder has been long-clicked. @@ -113,7 +113,7 @@ protected ReactiveRecyclerViewViewHolder(View view) /// /// The is the ViewModel of this ViewHolder in the . /// - public IObservable LongClickedWithViewModel { get; } + public IObservable LongClickedWithViewModel { get; } /// /// Gets the current view being shown. @@ -121,7 +121,7 @@ protected ReactiveRecyclerViewViewHolder(View view) public View View => ItemView; /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); @@ -134,10 +134,10 @@ public TViewModel ViewModel public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj b/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj index 5dcbb10ff3..b14dc9d7a3 100644 --- a/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj +++ b/src/ReactiveUI.AndroidX/ReactiveUI.AndroidX.csproj @@ -4,6 +4,7 @@ MonoAndroid90 Provides ReactiveUI extensions for the AndroidX Library ReactiveUI.AndroidX + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;xamarin;android;forms;monodroid;monotouch;xamarin.android;net; diff --git a/src/ReactiveUI.Blazor/PlatformOperations.cs b/src/ReactiveUI.Blazor/PlatformOperations.cs index 5895193b47..e8c782c74b 100644 --- a/src/ReactiveUI.Blazor/PlatformOperations.cs +++ b/src/ReactiveUI.Blazor/PlatformOperations.cs @@ -11,7 +11,7 @@ namespace ReactiveUI.Blazor public class PlatformOperations : IPlatformOperations { /// - public string GetOrientation() + public string? GetOrientation() { return null; } diff --git a/src/ReactiveUI.Blazor/ReactiveComponentBase.cs b/src/ReactiveUI.Blazor/ReactiveComponentBase.cs index 85d8edefa9..8b0415f7c3 100644 --- a/src/ReactiveUI.Blazor/ReactiveComponentBase.cs +++ b/src/ReactiveUI.Blazor/ReactiveComponentBase.cs @@ -29,21 +29,21 @@ public class ReactiveComponentBase : ComponentBase, IViewFor, INotifyPrope private readonly Subject _deactivateSubject = new Subject(); private readonly CompositeDisposable _compositeDisposable = new CompositeDisposable(); - private T _viewModel; + private T? _viewModel; private bool _disposedValue; // To detect redundant calls /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// [Parameter] - public T ViewModel + public T? ViewModel { get => _viewModel; set { - if (EqualityComparer.Default.Equals(_viewModel, value)) + if (EqualityComparer.Default.Equals(_viewModel, value)) { return; } @@ -54,10 +54,10 @@ public T ViewModel } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (T)value; + set => ViewModel = (T?)value; } /// @@ -106,8 +106,8 @@ protected override void OnAfterRender(bool firstRender) void Handler(object sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); return Handler; }, - eh => x.PropertyChanged += eh, - eh => x.PropertyChanged -= eh)) + eh => x!.PropertyChanged += eh, + eh => x!.PropertyChanged -= eh)) .Switch() .Subscribe(_ => InvokeAsync(StateHasChanged)) .DisposeWith(_compositeDisposable); @@ -120,7 +120,7 @@ protected override void OnAfterRender(bool firstRender) /// Invokes the property changed event. /// /// The name of the property. - protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null) + protected virtual void OnPropertyChanged([CallerMemberName]string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } diff --git a/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs b/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs index a1d1eb96a3..cab42eeb88 100644 --- a/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs +++ b/src/ReactiveUI.Blazor/ReactiveInjectableComponentBase.cs @@ -29,21 +29,21 @@ public class ReactiveInjectableComponentBase : ComponentBase, IViewFor, IN private readonly Subject _deactivateSubject = new Subject(); private readonly CompositeDisposable _compositeDisposable = new CompositeDisposable(); - private T _viewModel; + private T? _viewModel; private bool _disposedValue; // To detect redundant calls /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// [Inject] - public T ViewModel + public T? ViewModel { get => _viewModel; set { - if (EqualityComparer.Default.Equals(_viewModel, value)) + if (EqualityComparer.Default.Equals(_viewModel, value)) { return; } @@ -54,10 +54,10 @@ public T ViewModel } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (T)value; + set => ViewModel = (T?)value; } /// @@ -106,8 +106,8 @@ protected override void OnAfterRender(bool firstRender) void Handler(object sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); return Handler; }, - eh => x.PropertyChanged += eh, - eh => x.PropertyChanged -= eh)) + eh => x!.PropertyChanged += eh, + eh => x!.PropertyChanged -= eh)) .Switch() .Subscribe(_ => InvokeAsync(StateHasChanged)) .DisposeWith(_compositeDisposable); @@ -120,7 +120,7 @@ protected override void OnAfterRender(bool firstRender) /// Invokes the property changed event. /// /// The name of the property. - protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null) + protected virtual void OnPropertyChanged([CallerMemberName]string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } diff --git a/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs b/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs index e62ea9b400..8ee6cdca73 100644 --- a/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs +++ b/src/ReactiveUI.Blazor/ReactiveLayoutComponentBase.cs @@ -25,20 +25,20 @@ public class ReactiveLayoutComponentBase : LayoutComponentBase, IViewFor, { private readonly Subject _initSubject = new Subject(); - private T _viewModel; + private T? _viewModel; private bool _disposedValue; // To detect redundant calls /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// - public T ViewModel + public T? ViewModel { get => _viewModel; set { - if (EqualityComparer.Default.Equals(_viewModel, value)) + if (EqualityComparer.Default.Equals(_viewModel, value)) { return; } @@ -49,10 +49,10 @@ public T ViewModel } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (T)value; + set => ViewModel = (T?)value; } /// @@ -95,8 +95,8 @@ protected override void OnAfterRender(bool isFirstRender) void Handler(object sender, PropertyChangedEventArgs e) => eventHandler(Unit.Default); return Handler; }, - eh => x.PropertyChanged += eh, - eh => x.PropertyChanged -= eh)) + eh => x!.PropertyChanged += eh, + eh => x!.PropertyChanged -= eh)) .Switch() .Do(_ => InvokeAsync(StateHasChanged)) .Subscribe(); @@ -106,7 +106,7 @@ protected override void OnAfterRender(bool isFirstRender) /// Invokes the property changed event. /// /// The name of the property. - protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null) + protected virtual void OnPropertyChanged([CallerMemberName]string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } diff --git a/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj b/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj index 4c3aba1323..82d815a42c 100644 --- a/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj +++ b/src/ReactiveUI.Blazor/ReactiveUI.Blazor.csproj @@ -3,6 +3,8 @@ netstandard2.0 Contains the ReactiveUI platform specific extensions for Blazor mvvm;reactiveui;rx;reactive extensions;observable;LINQ;eventsnet;netstandard;blazor;web; + enable + latest diff --git a/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs b/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs index 7c7a82e5f9..75e1e5c2aa 100644 --- a/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs +++ b/src/ReactiveUI.Blend/FollowObservableStateBehavior.cs @@ -28,7 +28,7 @@ public class FollowObservableStateBehavior : Behavior public class FollowObservableStateBehavior : Behavior #endif { - private IDisposable _watcher; + private IDisposable? _watcher; /// /// Gets or sets the state observable. @@ -40,7 +40,7 @@ public IObservable StateObservable } /// - /// The state observable depdendency property. + /// The state observable dependency property. /// public static readonly DependencyProperty StateObservableProperty = DependencyProperty.Register("StateObservable", typeof(IObservable), typeof(FollowObservableStateBehavior), new PropertyMetadata(null, OnStateObservableChanged)); diff --git a/src/ReactiveUI.Blend/Platforms/net4/ObservableTrigger.cs b/src/ReactiveUI.Blend/Platforms/net4/ObservableTrigger.cs index bc03e7d8a7..29f7a21bee 100644 --- a/src/ReactiveUI.Blend/Platforms/net4/ObservableTrigger.cs +++ b/src/ReactiveUI.Blend/Platforms/net4/ObservableTrigger.cs @@ -24,7 +24,7 @@ public class ObservableTrigger : TriggerBase public static readonly DependencyProperty ObservableProperty = DependencyProperty.Register("Observable", typeof(IObservable), typeof(ObservableTrigger), new PropertyMetadata(OnObservableChanged)); - private IDisposable _watcher; + private IDisposable? _watcher; /// /// Gets or sets the observable which will activate the trigger. diff --git a/src/ReactiveUI.Blend/Platforms/uap/Behavior.cs b/src/ReactiveUI.Blend/Platforms/uap/Behavior.cs index 40e626b934..3ba1d1e026 100644 --- a/src/ReactiveUI.Blend/Platforms/uap/Behavior.cs +++ b/src/ReactiveUI.Blend/Platforms/uap/Behavior.cs @@ -21,10 +21,10 @@ public class Behavior : DependencyObject, IBehavior /// /// Gets the associated object. /// - public T AssociatedObject { get; private set; } + public T? AssociatedObject { get; private set; } /// - DependencyObject IBehavior.AssociatedObject => AssociatedObject; + DependencyObject? IBehavior.AssociatedObject => AssociatedObject; /// public virtual void Attach(DependencyObject associatedObject) diff --git a/src/ReactiveUI.Blend/Platforms/uap/ObservableTriggerBehavior.cs b/src/ReactiveUI.Blend/Platforms/uap/ObservableTriggerBehavior.cs index 9f27a7d91b..f2c8f0eb46 100644 --- a/src/ReactiveUI.Blend/Platforms/uap/ObservableTriggerBehavior.cs +++ b/src/ReactiveUI.Blend/Platforms/uap/ObservableTriggerBehavior.cs @@ -40,7 +40,7 @@ public sealed class ObservableTriggerBehavior : Behavior, IDis public static readonly DependencyProperty SourceObjectProperty = DependencyProperty.Register("SourceObject", typeof(object), typeof(ObservableTriggerBehavior), new PropertyMetadata(null, OnSourceObjectChanged)); - private object _resolvedSource; + private object? _resolvedSource; private SerialDisposable _watcher; /// @@ -140,7 +140,7 @@ private static void OnSourceObjectChanged(DependencyObject dependencyObject, Dep observableTriggerBehavior.SetResolvedSource(observableTriggerBehavior.ComputeResolvedSource()); } - private void SetResolvedSource(object newSource) + private void SetResolvedSource(object? newSource) { if (AssociatedObject == null || _resolvedSource == newSource) { @@ -150,7 +150,7 @@ private void SetResolvedSource(object newSource) _resolvedSource = newSource; } - private object ComputeResolvedSource() + private object? ComputeResolvedSource() { if (ReadLocalValue(ObservableTriggerBehavior.SourceObjectProperty) != DependencyProperty.UnsetValue) { diff --git a/src/ReactiveUI.Blend/ReactiveUI.Blend.csproj b/src/ReactiveUI.Blend/ReactiveUI.Blend.csproj index 14d69bff52..92198ce9aa 100644 --- a/src/ReactiveUI.Blend/ReactiveUI.Blend.csproj +++ b/src/ReactiveUI.Blend/ReactiveUI.Blend.csproj @@ -6,6 +6,7 @@ ReactiveUI.Blend Provides reactive extensions based xaml components based on the Blend SDK library, allowing you to fire a observable from XAML ReactiveUI.Blend + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;Blend;wpf;net; diff --git a/src/ReactiveUI.Drawing/ReactiveUI.Drawing.csproj b/src/ReactiveUI.Drawing/ReactiveUI.Drawing.csproj index 5a4ffd55fb..10f99260e4 100644 --- a/src/ReactiveUI.Drawing/ReactiveUI.Drawing.csproj +++ b/src/ReactiveUI.Drawing/ReactiveUI.Drawing.csproj @@ -6,6 +6,7 @@ ReactiveUI.Drawing A extension to the ReactiveUI platform that provides Splat bitmap operation support. ReactiveUI.Drawing + enable latest diff --git a/src/ReactiveUI.Fody.Analyzer.Test/Helpers/CodeFixVerifier.Helper.cs b/src/ReactiveUI.Fody.Analyzer.Test/Helpers/CodeFixVerifier.Helper.cs index c0c1594760..6843d69b3e 100644 --- a/src/ReactiveUI.Fody.Analyzer.Test/Helpers/CodeFixVerifier.Helper.cs +++ b/src/ReactiveUI.Fody.Analyzer.Test/Helpers/CodeFixVerifier.Helper.cs @@ -26,7 +26,7 @@ public abstract partial class CodeFixVerifier : DiagnosticVerifier /// The Document to apply the fix on. /// A CodeAction that will be applied to the Document. /// A Document with the changes from the CodeAction. - private static Document ApplyFix(Document document, CodeAction codeAction) + private static Document? ApplyFix(Document document, CodeAction codeAction) { var operations = codeAction.GetOperationsAsync(CancellationToken.None).Result; var solution = operations.OfType().Single().ChangedSolution; @@ -68,9 +68,9 @@ private static IEnumerable GetNewDiagnostics(IEnumerable /// /// The Document to run the compiler diagnostic analyzers on. /// The compiler diagnostics that were found in the code. - private static IEnumerable GetCompilerDiagnostics(Document document) + private static IEnumerable GetCompilerDiagnostics(Document? document) { - return document.GetSemanticModelAsync().Result.GetDiagnostics(); + return document?.GetSemanticModelAsync()?.Result?.GetDiagnostics() ?? Enumerable.Empty(); } /// diff --git a/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticResult.cs b/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticResult.cs index 09a43aedf3..318b1891e9 100644 --- a/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticResult.cs +++ b/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticResult.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; + using Microsoft.CodeAnalysis; namespace TestHelper @@ -12,13 +13,14 @@ namespace TestHelper /// /// Struct that stores information about a Diagnostic appearing in a source. /// - public struct DiagnosticResult + public struct DiagnosticResult : IEquatable { private IList _locations; /// /// Gets or sets the locations of the Analysis Result. /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Deliberate usage.")] public IList Locations { get @@ -84,5 +86,61 @@ public int Column return Locations.Count > 0 ? Locations[0].Column : -1; } } + + /// + /// Performs equality against left and right. + /// + /// Left side to compare. + /// Right side to compare. + /// If the two values are equal. + public static bool operator ==(DiagnosticResult left, DiagnosticResult right) + { + return left.Equals(right); + } + + /// + /// Performs inequality against left and right. + /// + /// Left side to compare. + /// Right side to compare. + /// If the two values are not equal. + public static bool operator !=(DiagnosticResult left, DiagnosticResult right) + { + return !(left == right); + } + + /// + public override bool Equals(object? obj) + { + return obj is DiagnosticResult result && Equals(result); + } + + /// + public bool Equals(DiagnosticResult other) + { + return EqualityComparer>.Default.Equals(_locations, other._locations) && + EqualityComparer>.Default.Equals(Locations, other.Locations) && + Severity == other.Severity && + Id == other.Id && + Message == other.Message && + Path == other.Path && + Line == other.Line && + Column == other.Column; + } + + /// + public override int GetHashCode() + { + int hashCode = 1054991603; + hashCode = (hashCode * -1521134295) + EqualityComparer>.Default.GetHashCode(_locations); + hashCode = (hashCode * -1521134295) + EqualityComparer>.Default.GetHashCode(Locations); + hashCode = (hashCode * -1521134295) + Severity.GetHashCode(); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Id); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Message); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Path); + hashCode = (hashCode * -1521134295) + Line.GetHashCode(); + hashCode = (hashCode * -1521134295) + Column.GetHashCode(); + return hashCode; + } } } diff --git a/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticVerifier.Helper.cs b/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticVerifier.Helper.cs index 1ffb62045b..0c0493d6a1 100644 --- a/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticVerifier.Helper.cs +++ b/src/ReactiveUI.Fody.Analyzer.Test/Helpers/DiagnosticVerifier.Helper.cs @@ -57,8 +57,14 @@ protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyz var diagnostics = new List(); foreach (var project in projects) { - var compilationWithAnalyzers = project.GetCompilationAsync().Result.WithAnalyzers(ImmutableArray.Create(analyzer)); - var diags = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().Result; + var compilationWithAnalyzers = project.GetCompilationAsync().Result?.WithAnalyzers(ImmutableArray.Create(analyzer)); + var diags = compilationWithAnalyzers?.GetAnalyzerDiagnosticsAsync().Result; + + if (diags == null) + { + continue; + } + foreach (var diag in diags) { if (diag.Location == Location.None || diag.Location.IsInMetadata) @@ -91,9 +97,9 @@ protected static Diagnostic[] GetSortedDiagnosticsFromDocuments(DiagnosticAnalyz /// Classes in the form of a string. /// The language the source code is in. /// A Document created from the source string. - protected static Document CreateDocument(string source, string language = LanguageNames.CSharp) + protected static Document? CreateDocument(string source, string language = LanguageNames.CSharp) { - return CreateProject(new[] { source }, language).Documents.First(); + return CreateProject(new[] { source }, language)?.Documents.First(); } /// @@ -132,7 +138,7 @@ private static Document[] GetDocuments(string[] sources, string language) } var project = CreateProject(sources, language); - var documents = project.Documents.ToArray(); + var documents = project?.Documents.ToArray() ?? Array.Empty(); if (sources.Length != documents.Length) { @@ -148,7 +154,7 @@ private static Document[] GetDocuments(string[] sources, string language) /// Classes in the form of strings. /// The language the source code is in. /// A Project created out of the Documents created from the source strings. - private static Project CreateProject(string[] sources, string language = LanguageNames.CSharp) + private static Project? CreateProject(string[] sources, string language = LanguageNames.CSharp) { string fileNamePrefix = DefaultFilePathPrefix; string fileExt = language == LanguageNames.CSharp ? CSharpDefaultFileExt : VisualBasicDefaultExt; diff --git a/src/ReactiveUI.Fody.Analyzer.Test/ReactiveUI.Fody.Analyzer.Test.csproj b/src/ReactiveUI.Fody.Analyzer.Test/ReactiveUI.Fody.Analyzer.Test.csproj index 1baaf21f78..49a79e9e4f 100644 --- a/src/ReactiveUI.Fody.Analyzer.Test/ReactiveUI.Fody.Analyzer.Test.csproj +++ b/src/ReactiveUI.Fody.Analyzer.Test/ReactiveUI.Fody.Analyzer.Test.csproj @@ -1,20 +1,20 @@  - - net461 - - - - - - - - - - - - - - - - + + netcoreapp3.1 + $(TargetFrameworks);net461 + enable + latest + + + + + + + + + + + + + diff --git a/src/ReactiveUI.Fody.Analyzer.Test/Verifiers/DiagnosticVerifier.cs b/src/ReactiveUI.Fody.Analyzer.Test/Verifiers/DiagnosticVerifier.cs index 5b60233a57..f63b22eaa2 100644 --- a/src/ReactiveUI.Fody.Analyzer.Test/Verifiers/DiagnosticVerifier.cs +++ b/src/ReactiveUI.Fody.Analyzer.Test/Verifiers/DiagnosticVerifier.cs @@ -25,7 +25,7 @@ public abstract partial class DiagnosticVerifier /// DiagnosticAnalyzer to be tested. protected virtual DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() { - return null; + return null!; } /// @@ -34,7 +34,7 @@ protected virtual DiagnosticAnalyzer GetCSharpDiagnosticAnalyzer() /// DiagnosticAnalyzer to be tested. protected virtual DiagnosticAnalyzer GetBasicDiagnosticAnalyzer() { - return null; + return null!; } /// @@ -228,7 +228,7 @@ private static string FormatDiagnostics(DiagnosticAnalyzer analyzer, params Diag location.IsInSource, $"Test base does not currently handle diagnostics in metadata locations. Diagnostic in metadata: {diagnostics[i]}\r\n"); - string resultMethodName = diagnostics[i].Location.SourceTree.FilePath.EndsWith(".cs", StringComparison.Ordinal) ? "GetCSharpResultAt" : "GetBasicResultAt"; + string resultMethodName = diagnostics[i].Location.SourceTree!.FilePath.EndsWith(".cs", StringComparison.Ordinal) ? "GetCSharpResultAt" : "GetBasicResultAt"; var linePosition = diagnostics[i].Location.GetLineSpan().StartLinePosition; builder.Append($"{resultMethodName}({linePosition.Line + 1}, {linePosition.Character + 1}, {analyzerType.Name}.{rule.Id})"); diff --git a/src/ReactiveUI.Fody.Analyzer/ReactiveObjectAnalyzer.cs b/src/ReactiveUI.Fody.Analyzer/ReactiveObjectAnalyzer.cs index ae8cc3538f..0e9a40c229 100644 --- a/src/ReactiveUI.Fody.Analyzer/ReactiveObjectAnalyzer.cs +++ b/src/ReactiveUI.Fody.Analyzer/ReactiveObjectAnalyzer.cs @@ -64,39 +64,45 @@ public override void Initialize(AnalysisContext context) private static void AnalyzeAttribute(SyntaxNodeAnalysisContext context) { - var attr = context.ContainingSymbol + var attr = context.ContainingSymbol? .GetAttributes() - .FirstOrDefault(a => a.ApplicationSyntaxReference.Span == context.Node.Span); + .FirstOrDefault(a => a.ApplicationSyntaxReference!.Span == context.Node.Span); - if (attr.AttributeClass.ToDisplayString() != "ReactiveUI.Fody.Helpers.ReactiveAttribute") + if (attr?.AttributeClass?.ToDisplayString() != "ReactiveUI.Fody.Helpers.ReactiveAttribute") { return; } - if (!(context.Node.Parent.Parent is PropertyDeclarationSyntax property)) + if (!(context.Node.Parent?.Parent is PropertyDeclarationSyntax property)) { return; } - var reactiveObject = context.ContainingSymbol.ContainingType; - if (!reactiveObject.AllInterfaces.Any(interfaceTypeSymbol => interfaceTypeSymbol.ToDisplayString() == "ReactiveUI.IReactiveObject")) + if (context.ContainingSymbol != null) { - context.ReportDiagnostic( - Diagnostic.Create( - InheritanceRule, - context.Node.GetLocation(), - reactiveObject.Name)); + var reactiveObject = context.ContainingSymbol.ContainingType; + if (!reactiveObject.AllInterfaces.Any(interfaceTypeSymbol => interfaceTypeSymbol.ToDisplayString() == "ReactiveUI.IReactiveObject")) + { + context.ReportDiagnostic( + Diagnostic.Create( + InheritanceRule, + context.Node.GetLocation(), + reactiveObject.Name)); + } } if (HasBackingField(property)) { var propertySymbol = context.ContainingSymbol; - context.ReportDiagnostic( - Diagnostic.Create( - AutoPropertyRule, - context.Node.GetLocation(), - propertySymbol.Name, - propertySymbol.ContainingType.Name)); + if (propertySymbol != null) + { + context.ReportDiagnostic( + Diagnostic.Create( + AutoPropertyRule, + context.Node.GetLocation(), + propertySymbol.Name, + propertySymbol.ContainingType.Name)); + } } } diff --git a/src/ReactiveUI.Fody.Analyzer/ReactiveUI.Fody.Analyzer.csproj b/src/ReactiveUI.Fody.Analyzer/ReactiveUI.Fody.Analyzer.csproj index db502b8a60..cdbdd1aad2 100644 --- a/src/ReactiveUI.Fody.Analyzer/ReactiveUI.Fody.Analyzer.csproj +++ b/src/ReactiveUI.Fody.Analyzer/ReactiveUI.Fody.Analyzer.csproj @@ -4,6 +4,7 @@ ReactiveUI.Fody.Analyzer ReactiveUI.Fody.Analyzer Rosyln extension that checks correct usage of the Fody extension. + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;xamarin;android;ios;mac;forms;monodroid;monotouch;xamarin.android;xamarin.ios;xamarin.forms;xamarin.mac;xamarin.tvos;wpf;net;netstandard;net461;uwp;tizen;unoplatform;fody; False diff --git a/src/ReactiveUI.Fody.Helpers/ObservableAsPropertyExtensions.cs b/src/ReactiveUI.Fody.Helpers/ObservableAsPropertyExtensions.cs index b85596a9e7..ff2dd963be 100644 --- a/src/ReactiveUI.Fody.Helpers/ObservableAsPropertyExtensions.cs +++ b/src/ReactiveUI.Fody.Helpers/ObservableAsPropertyExtensions.cs @@ -32,7 +32,7 @@ public static class ObservableAsPropertyExtensions /// or /// Backing field not found for " + propertyInfo. /// - public static ObservableAsPropertyHelper ToPropertyEx(this IObservable item, TObj source, Expression> property, TRet initialValue = default, bool deferSubscription = false, IScheduler scheduler = null) + public static ObservableAsPropertyHelper ToPropertyEx(this IObservable item, TObj source, Expression> property, TRet initialValue = default, bool deferSubscription = false, IScheduler? scheduler = null) where TObj : ReactiveObject { if (item == null) diff --git a/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs b/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs index e87fb7e16b..9e2a2b193f 100644 --- a/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs +++ b/src/ReactiveUI.Fody.Helpers/ReactiveDependencyAttribute.cs @@ -35,6 +35,6 @@ public ReactiveDependencyAttribute(string targetName) /// /// Gets or sets the target property on the backing property. /// - public string TargetProperty { get; set; } + public string? TargetProperty { get; set; } } } diff --git a/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj b/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj index 5e4299a3ad..6e14038a22 100644 --- a/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj +++ b/src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj @@ -12,6 +12,7 @@ false + enable latest diff --git a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.net461.approved.txt b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.net461.approved.txt index a019371da0..f5e35983fc 100644 --- a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.net461.approved.txt +++ b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.net461.approved.txt @@ -13,7 +13,7 @@ namespace ReactiveUI.Fody.Helpers } public static class ObservableAsPropertyExtensions { - public static ReactiveUI.ObservableAsPropertyHelper ToPropertyEx(this System.IObservable item, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToPropertyEx(this System.IObservable item, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : ReactiveUI.ReactiveObject { } } [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.All)] @@ -26,6 +26,6 @@ namespace ReactiveUI.Fody.Helpers { public ReactiveDependencyAttribute(string targetName) { } public string Target { get; } - public string TargetProperty { get; set; } + public string? TargetProperty { get; set; } } } \ No newline at end of file diff --git a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.netcoreapp3.1.approved.txt b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.netcoreapp3.1.approved.txt index 1af8ba5cdb..bea9ef126e 100644 --- a/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.netcoreapp3.1.approved.txt +++ b/src/ReactiveUI.Fody.Tests/API/ApiApprovalTests.ReactiveUIFody.netcoreapp3.1.approved.txt @@ -13,7 +13,7 @@ namespace ReactiveUI.Fody.Helpers } public static class ObservableAsPropertyExtensions { - public static ReactiveUI.ObservableAsPropertyHelper ToPropertyEx(this System.IObservable item, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToPropertyEx(this System.IObservable item, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : ReactiveUI.ReactiveObject { } } [System.AttributeUsage(System.AttributeTargets.Property | System.AttributeTargets.All)] @@ -26,6 +26,6 @@ namespace ReactiveUI.Fody.Helpers { public ReactiveDependencyAttribute(string targetName) { } public string Target { get; } - public string TargetProperty { get; set; } + public string? TargetProperty { get; set; } } } \ No newline at end of file diff --git a/src/ReactiveUI.Fody.Tests/ApiApprovalBase.cs b/src/ReactiveUI.Fody.Tests/ApiApprovalBase.cs index 2f326c0827..60b204c4d7 100644 --- a/src/ReactiveUI.Fody.Tests/ApiApprovalBase.cs +++ b/src/ReactiveUI.Fody.Tests/ApiApprovalBase.cs @@ -25,31 +25,34 @@ public abstract class ApiApprovalBase { private static readonly Regex _removeCoverletSectionRegex = new Regex(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled); - protected static void CheckApproval(Assembly assembly, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null) + protected static void CheckApproval(Assembly assembly, [CallerMemberName]string? memberName = null, [CallerFilePath]string? filePath = null) { var targetFrameworkName = Assembly.GetExecutingAssembly().GetTargetFrameworkName(); var sourceDirectory = Path.GetDirectoryName(filePath); - var approvedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.approved.txt"); - var receivedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.received.txt"); + if (sourceDirectory != null) + { + var approvedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.approved.txt"); + var receivedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.received.txt"); - string approvedPublicApi = string.Empty; + string approvedPublicApi = string.Empty; - if (File.Exists(approvedFileName)) - { - approvedPublicApi = File.ReadAllText(approvedFileName); - } + if (File.Exists(approvedFileName)) + { + approvedPublicApi = File.ReadAllText(approvedFileName); + } - var receivedPublicApi = Filter(ApiGenerator.GeneratePublicApi(assembly, new ApiGeneratorOptions())); + var receivedPublicApi = Filter(ApiGenerator.GeneratePublicApi(assembly, new ApiGeneratorOptions())); - if (!string.Equals(receivedPublicApi, approvedPublicApi, StringComparison.InvariantCulture)) - { - File.WriteAllText(receivedFileName, receivedPublicApi); - ShouldlyConfiguration.DiffTools.GetDiffTool().Open(receivedFileName, approvedFileName, true); - } + if (!string.Equals(receivedPublicApi, approvedPublicApi, StringComparison.InvariantCulture)) + { + File.WriteAllText(receivedFileName, receivedPublicApi); + ShouldlyConfiguration.DiffTools.GetDiffTool().Open(receivedFileName, approvedFileName, true); + } - Assert.Equal(approvedPublicApi, receivedPublicApi); + Assert.Equal(approvedPublicApi, receivedPublicApi); + } } private static string Filter(string text) diff --git a/src/ReactiveUI.Fody.Tests/FodyWeavers.xsd b/src/ReactiveUI.Fody.Tests/FodyWeavers.xsd index 5cedd530b9..f3ac47620a 100644 --- a/src/ReactiveUI.Fody.Tests/FodyWeavers.xsd +++ b/src/ReactiveUI.Fody.Tests/FodyWeavers.xsd @@ -4,7 +4,6 @@ - diff --git a/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs b/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs index 867f6a12ca..b5e0f10c36 100644 --- a/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs +++ b/src/ReactiveUI.Fody.Tests/Issues/Issue10Tests.cs @@ -28,7 +28,7 @@ public TestModel() } [ObservableAsProperty] - public string MyProperty { get; private set; } + public string? MyProperty { get; private set; } [ObservableAsProperty] public int MyIntProperty { get; private set; } @@ -36,7 +36,7 @@ public TestModel() [ObservableAsProperty] public DateTime MyDateTimeProperty { get; private set; } - public string OtherProperty { get; private set; } + public string? OtherProperty { get; private set; } } } } diff --git a/src/ReactiveUI.Fody.Tests/Mocks/BaseModel.cs b/src/ReactiveUI.Fody.Tests/Mocks/BaseModel.cs index c98fdf1e4a..08223fc741 100644 --- a/src/ReactiveUI.Fody.Tests/Mocks/BaseModel.cs +++ b/src/ReactiveUI.Fody.Tests/Mocks/BaseModel.cs @@ -15,6 +15,6 @@ public class BaseModel : ReactiveObject { public virtual int IntProperty { get; set; } = 5; - public virtual string StringProperty { get; set; } = "Initial Value"; + public virtual string? StringProperty { get; set; } = "Initial Value"; } } diff --git a/src/ReactiveUI.Fody.Tests/Mocks/DecoratorModel.cs b/src/ReactiveUI.Fody.Tests/Mocks/DecoratorModel.cs index 97f6d4b426..469be4ca40 100644 --- a/src/ReactiveUI.Fody.Tests/Mocks/DecoratorModel.cs +++ b/src/ReactiveUI.Fody.Tests/Mocks/DecoratorModel.cs @@ -28,11 +28,11 @@ public DecoratorModel(BaseModel baseModel) } [Reactive] - public string SomeCoolNewProperty { get; set; } + public string? SomeCoolNewProperty { get; set; } // Works with private fields [ReactiveDependency(nameof(_model))] - public override string StringProperty { get; set; } + public override string? StringProperty { get; set; } // Can't be attributed as has additional functionality in the decorated get public override int IntProperty diff --git a/src/ReactiveUI.Fody.Tests/Mocks/FacadeModel.cs b/src/ReactiveUI.Fody.Tests/Mocks/FacadeModel.cs index afb84771ec..da881cd18d 100644 --- a/src/ReactiveUI.Fody.Tests/Mocks/FacadeModel.cs +++ b/src/ReactiveUI.Fody.Tests/Mocks/FacadeModel.cs @@ -38,6 +38,6 @@ public BaseModel Dependency // Property named differently to that on the dependency but still pass through value [ReactiveDependency(nameof(Dependency), TargetProperty = "StringProperty")] - public string AnotherStringProperty { get; set; } + public string? AnotherStringProperty { get; set; } } } diff --git a/src/ReactiveUI.Fody.Tests/Mocks/ObservableAsTestModel.cs b/src/ReactiveUI.Fody.Tests/Mocks/ObservableAsTestModel.cs index 42a06877ef..a294c8f36b 100644 --- a/src/ReactiveUI.Fody.Tests/Mocks/ObservableAsTestModel.cs +++ b/src/ReactiveUI.Fody.Tests/Mocks/ObservableAsTestModel.cs @@ -21,6 +21,6 @@ public ObservableAsTestModel() } [ObservableAsProperty] - public string TestProperty { get; private set; } + public string? TestProperty { get; private set; } } } diff --git a/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj b/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj index 8b03d993d7..b7c48d0f86 100644 --- a/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj +++ b/src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj @@ -4,6 +4,7 @@ $(TargetFrameworks);net461 netstandard2.0 $(TargetFramework) + enable latest diff --git a/src/ReactiveUI.Fody/CecilExtensions.cs b/src/ReactiveUI.Fody/CecilExtensions.cs index e507923e4a..aa22cabd3f 100644 --- a/src/ReactiveUI.Fody/CecilExtensions.cs +++ b/src/ReactiveUI.Fody/CecilExtensions.cs @@ -67,7 +67,7 @@ public static GenericInstanceMethod MakeGenericMethod(this MethodReference metho /// /// true if [is assignable from] [the specified type]; otherwise, false. /// - public static bool IsAssignableFrom(this TypeReference baseType, TypeReference type, Action logger = null) + public static bool IsAssignableFrom(this TypeReference baseType, TypeReference type, Action? logger = null) { if (baseType == null) { @@ -91,9 +91,9 @@ public static bool IsAssignableFrom(this TypeReference baseType, TypeReference t /// /// true if [is assignable from] [the specified type]; otherwise, false. /// - public static bool IsAssignableFrom(this TypeDefinition baseType, TypeDefinition type, Action logger = null) + public static bool IsAssignableFrom(this TypeDefinition baseType, TypeDefinition type, Action? logger = null) { - logger = logger ?? (x => { }); + logger ??= x => { }; Queue queue = new Queue(); queue.Enqueue(type); @@ -226,7 +226,7 @@ public static AssemblyNameReference FindAssembly(this ModuleDefinition currentMo /// The scope. /// The type parameters. /// The type reference. - public static TypeReference FindType(this ModuleDefinition currentModule, string @namespace, string typeName, IMetadataScope scope = null, params string[] typeParameters) + public static TypeReference FindType(this ModuleDefinition currentModule, string @namespace, string typeName, IMetadataScope? scope = null, params string[] typeParameters) { if (typeParameters == null) { diff --git a/src/ReactiveUI.Fody/ModuleWeaver.cs b/src/ReactiveUI.Fody/ModuleWeaver.cs index 62b722210f..a93953a93e 100644 --- a/src/ReactiveUI.Fody/ModuleWeaver.cs +++ b/src/ReactiveUI.Fody/ModuleWeaver.cs @@ -20,24 +20,24 @@ public override void Execute() var propertyWeaver = new ReactiveUIPropertyWeaver { ModuleDefinition = ModuleDefinition, - LogInfo = LogInfo, - LogError = LogError + LogInfo = WriteInfo, + LogError = WriteError }; propertyWeaver.Execute(); var observableAsPropertyWeaver = new ObservableAsPropertyWeaver { ModuleDefinition = ModuleDefinition, - LogInfo = LogInfo, - FindType = FindType + LogInfo = WriteInfo, + FindType = FindTypeDefinition }; observableAsPropertyWeaver.Execute(); var reactiveDependencyWeaver = new ReactiveDependencyPropertyWeaver { ModuleDefinition = ModuleDefinition, - LogInfo = LogInfo, - LogError = LogError + LogInfo = WriteInfo, + LogError = WriteError }; reactiveDependencyWeaver.Execute(); } diff --git a/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs b/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs index 0482060df6..cb17f2b310 100644 --- a/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs +++ b/src/ReactiveUI.Fody/ObservableAsPropertyWeaver.cs @@ -22,7 +22,7 @@ public class ObservableAsPropertyWeaver /// /// The module definition. /// - public ModuleDefinition ModuleDefinition { get; set; } + public ModuleDefinition? ModuleDefinition { get; set; } /// /// Gets or sets a action that will log an MessageImportance.High message to MSBuild. OPTIONAL. @@ -30,93 +30,96 @@ public class ObservableAsPropertyWeaver /// /// The log information. /// - public Action LogInfo { get; set; } + public Action? LogInfo { get; set; } /// /// Gets a function that will find a type from referenced assemblies by name. /// - public Func FindType { get; internal set; } + public Func? FindType { get; internal set; } /// /// Executes this property weaver. /// public void Execute() { - var reactiveUI = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault(); + var reactiveUI = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault(); if (reactiveUI == null) { - LogInfo("Could not find assembly: ReactiveUI (" + string.Join(", ", ModuleDefinition.AssemblyReferences.Select(x => x.Name)) + ")"); + LogInfo?.Invoke("Could not find assembly: ReactiveUI (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")"); return; } - LogInfo($"{reactiveUI.Name} {reactiveUI.Version}"); - var helpers = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "ReactiveUI.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault(); + LogInfo?.Invoke($"{reactiveUI.Name} {reactiveUI.Version}"); + var helpers = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault(); if (helpers == null) { - LogInfo("Could not find assembly: ReactiveUI.Fody.Helpers (" + string.Join(", ", ModuleDefinition.AssemblyReferences.Select(x => x.Name)) + ")"); + LogInfo?.Invoke("Could not find assembly: ReactiveUI.Fody.Helpers (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")"); return; } - LogInfo($"{helpers.Name} {helpers.Version}"); + LogInfo?.Invoke($"{helpers.Name} {helpers.Version}"); - var reactiveObject = ModuleDefinition.FindType("ReactiveUI", "ReactiveObject", reactiveUI); + if (ModuleDefinition != null) + { + var reactiveObject = ModuleDefinition.FindType("ReactiveUI", "ReactiveObject", reactiveUI); - // The types we will scan are subclasses of ReactiveObject - var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType != null && reactiveObject.IsAssignableFrom(x.BaseType)); + // The types we will scan are subclasses of ReactiveObject + var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType != null && reactiveObject.IsAssignableFrom(x.BaseType)); - var observableAsPropertyHelper = ModuleDefinition.FindType("ReactiveUI", "ObservableAsPropertyHelper`1", reactiveUI, "T"); - var observableAsPropertyAttribute = ModuleDefinition.FindType("ReactiveUI.Fody.Helpers", "ObservableAsPropertyAttribute", helpers); - var observableAsPropertyHelperGetValue = ModuleDefinition.ImportReference(observableAsPropertyHelper.Resolve().Properties.Single(x => x.Name == "Value").GetMethod); - var exceptionDefinition = FindType(typeof(Exception).FullName); - var constructorDefinition = exceptionDefinition.GetConstructors().Single(x => x.Parameters.Count == 1); - var exceptionConstructor = ModuleDefinition.ImportReference(constructorDefinition); + var observableAsPropertyHelper = ModuleDefinition.FindType("ReactiveUI", "ObservableAsPropertyHelper`1", reactiveUI, "T"); + var observableAsPropertyAttribute = ModuleDefinition.FindType("ReactiveUI.Fody.Helpers", "ObservableAsPropertyAttribute", helpers); + var observableAsPropertyHelperGetValue = ModuleDefinition.ImportReference(observableAsPropertyHelper.Resolve().Properties.Single(x => x.Name == "Value").GetMethod); + var exceptionDefinition = FindType?.Invoke(typeof(Exception).FullName); + var constructorDefinition = exceptionDefinition.GetConstructors().Single(x => x.Parameters.Count == 1); + var exceptionConstructor = ModuleDefinition.ImportReference(constructorDefinition); - foreach (var targetType in targetTypes) - { - foreach (var property in targetType.Properties.Where(x => x.IsDefined(observableAsPropertyAttribute) || (x.GetMethod?.IsDefined(observableAsPropertyAttribute) ?? false)).ToArray()) + foreach (var targetType in targetTypes) { - var genericObservableAsPropertyHelper = observableAsPropertyHelper.MakeGenericInstanceType(property.PropertyType); - var genericObservableAsPropertyHelperGetValue = observableAsPropertyHelperGetValue.Bind(genericObservableAsPropertyHelper); - ModuleDefinition.ImportReference(genericObservableAsPropertyHelperGetValue); + foreach (var property in targetType.Properties.Where(x => x.IsDefined(observableAsPropertyAttribute) || (x.GetMethod?.IsDefined(observableAsPropertyAttribute) ?? false)).ToArray()) + { + var genericObservableAsPropertyHelper = observableAsPropertyHelper.MakeGenericInstanceType(property.PropertyType); + var genericObservableAsPropertyHelperGetValue = observableAsPropertyHelperGetValue.Bind(genericObservableAsPropertyHelper); + ModuleDefinition.ImportReference(genericObservableAsPropertyHelperGetValue); - // Declare a field to store the property value - var field = new FieldDefinition("$" + property.Name, FieldAttributes.Private, genericObservableAsPropertyHelper); - targetType.Fields.Add(field); + // Declare a field to store the property value + var field = new FieldDefinition("$" + property.Name, FieldAttributes.Private, genericObservableAsPropertyHelper); + targetType.Fields.Add(field); - // It's an auto-property, so remove the generated field - if (property.SetMethod != null && property.SetMethod.HasBody) - { - // Remove old field (the generated backing field for the auto property) - var oldField = (FieldReference)property.GetMethod.Body.Instructions.Where(x => x.Operand is FieldReference).Single().Operand; - var oldFieldDefinition = oldField.Resolve(); - targetType.Fields.Remove(oldFieldDefinition); - - // Re-implement setter to throw an exception - property.SetMethod.Body = new MethodBody(property.SetMethod); - property.SetMethod.Body.Emit(il => + // It's an auto-property, so remove the generated field + if (property.SetMethod != null && property.SetMethod.HasBody) { - il.Emit(OpCodes.Ldstr, "Never call the setter of an ObservabeAsPropertyHelper property."); - il.Emit(OpCodes.Newobj, exceptionConstructor); - il.Emit(OpCodes.Throw); - il.Emit(OpCodes.Ret); + // Remove old field (the generated backing field for the auto property) + var oldField = (FieldReference)property.GetMethod.Body.Instructions.Where(x => x.Operand is FieldReference).Single().Operand; + var oldFieldDefinition = oldField.Resolve(); + targetType.Fields.Remove(oldFieldDefinition); + + // Re-implement setter to throw an exception + property.SetMethod.Body = new MethodBody(property.SetMethod); + property.SetMethod.Body.Emit(il => + { + il.Emit(OpCodes.Ldstr, "Never call the setter of an ObservabeAsPropertyHelper property."); + il.Emit(OpCodes.Newobj, exceptionConstructor); + il.Emit(OpCodes.Throw); + il.Emit(OpCodes.Ret); + }); + } + + property.GetMethod.Body = new MethodBody(property.GetMethod); + property.GetMethod.Body.Emit(il => + { + var isValid = il.Create(OpCodes.Nop); + il.Emit(OpCodes.Ldarg_0); // this + il.Emit(OpCodes.Ldfld, field.BindDefinition(targetType)); // pop -> this.$PropertyName + il.Emit(OpCodes.Dup); // Put an extra copy of this.$PropertyName onto the stack + il.Emit(OpCodes.Brtrue, isValid); // If the helper is null, return the default value for the property + il.Emit(OpCodes.Pop); // Drop this.$PropertyName + EmitDefaultValue(property.GetMethod.Body, il, property.PropertyType); // Put the default value onto the stack + il.Emit(OpCodes.Ret); // Return that default value + il.Append(isValid); // Add a marker for if the helper is not null + il.Emit(OpCodes.Callvirt, genericObservableAsPropertyHelperGetValue); // pop -> this.$PropertyName.Value + il.Emit(OpCodes.Ret); // Return the value that is on the stack }); } - - property.GetMethod.Body = new MethodBody(property.GetMethod); - property.GetMethod.Body.Emit(il => - { - var isValid = il.Create(OpCodes.Nop); - il.Emit(OpCodes.Ldarg_0); // this - il.Emit(OpCodes.Ldfld, field.BindDefinition(targetType)); // pop -> this.$PropertyName - il.Emit(OpCodes.Dup); // Put an extra copy of this.$PropertyName onto the stack - il.Emit(OpCodes.Brtrue, isValid); // If the helper is null, return the default value for the property - il.Emit(OpCodes.Pop); // Drop this.$PropertyName - EmitDefaultValue(property.GetMethod.Body, il, property.PropertyType); // Put the default value onto the stack - il.Emit(OpCodes.Ret); // Return that default value - il.Append(isValid); // Add a marker for if the helper is not null - il.Emit(OpCodes.Callvirt, genericObservableAsPropertyHelperGetValue); // pop -> this.$PropertyName.Value - il.Emit(OpCodes.Ret); // Return the value that is on the stack - }); } } } @@ -139,35 +142,38 @@ public void EmitDefaultValue(MethodBody methodBody, ILProcessor il, TypeReferenc throw new ArgumentNullException(nameof(il)); } - if (type.CompareTo(ModuleDefinition.TypeSystem.Boolean) || type.CompareTo(ModuleDefinition.TypeSystem.Byte) || - type.CompareTo(ModuleDefinition.TypeSystem.Int16) || type.CompareTo(ModuleDefinition.TypeSystem.Int32)) - { - il.Emit(OpCodes.Ldc_I4_0); - } - else if (type.CompareTo(ModuleDefinition.TypeSystem.Single)) - { - il.Emit(OpCodes.Ldc_R4, 0F); - } - else if (type.CompareTo(ModuleDefinition.TypeSystem.Int64)) - { - il.Emit(OpCodes.Ldc_I8); - } - else if (type.CompareTo(ModuleDefinition.TypeSystem.Double)) - { - il.Emit(OpCodes.Ldc_R8, 0D); - } - else if (type.IsGenericParameter || type.IsValueType) + if (ModuleDefinition != null) { - methodBody.InitLocals = true; - var local = new VariableDefinition(type); - il.Body.Variables.Add(local); - il.Emit(OpCodes.Ldloca_S, local); - il.Emit(OpCodes.Initobj, type); - il.Emit(OpCodes.Ldloc, local); - } - else - { - il.Emit(OpCodes.Ldnull); + if (type.CompareTo(ModuleDefinition.TypeSystem.Boolean) || type.CompareTo(ModuleDefinition.TypeSystem.Byte) || + type.CompareTo(ModuleDefinition.TypeSystem.Int16) || type.CompareTo(ModuleDefinition.TypeSystem.Int32)) + { + il.Emit(OpCodes.Ldc_I4_0); + } + else if (type.CompareTo(ModuleDefinition.TypeSystem.Single)) + { + il.Emit(OpCodes.Ldc_R4, 0F); + } + else if (type.CompareTo(ModuleDefinition.TypeSystem.Int64)) + { + il.Emit(OpCodes.Ldc_I8); + } + else if (type.CompareTo(ModuleDefinition.TypeSystem.Double)) + { + il.Emit(OpCodes.Ldc_R8, 0D); + } + else if (type.IsGenericParameter || type.IsValueType) + { + methodBody.InitLocals = true; + var local = new VariableDefinition(type); + il.Body.Variables.Add(local); + il.Emit(OpCodes.Ldloca_S, local); + il.Emit(OpCodes.Initobj, type); + il.Emit(OpCodes.Ldloc, local); + } + else + { + il.Emit(OpCodes.Ldnull); + } } } } diff --git a/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs b/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs index d140fa1a44..dd8f6e0ac5 100644 --- a/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs +++ b/src/ReactiveUI.Fody/ReactiveDependencyPropertyWeaver.cs @@ -22,7 +22,7 @@ public class ReactiveDependencyPropertyWeaver /// /// The module definition. /// - public ModuleDefinition ModuleDefinition { get; set; } + public ModuleDefinition? ModuleDefinition { get; set; } /// /// Gets or sets a action that will log an MessageImportance.High message to MSBuild. OPTIONAL. @@ -30,7 +30,7 @@ public class ReactiveDependencyPropertyWeaver /// /// The log information. /// - public Action LogInfo { get; set; } + public Action? LogInfo { get; set; } /// /// Gets or sets a action which will log an error message to MSBuild. OPTIONAL. @@ -38,7 +38,7 @@ public class ReactiveDependencyPropertyWeaver /// /// The log error. /// - public Action LogError { get; set; } + public Action? LogError { get; set; } /// /// Executes this instance. @@ -52,22 +52,22 @@ public class ReactiveDependencyPropertyWeaver /// public void Execute() { - var reactiveUI = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault(); + var reactiveUI = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault(); if (reactiveUI == null) { - LogInfo("Could not find assembly: ReactiveUI (" + string.Join(", ", ModuleDefinition.AssemblyReferences.Select(x => x.Name)) + ")"); + LogInfo?.Invoke("Could not find assembly: ReactiveUI (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")"); return; } - LogInfo($"{reactiveUI.Name} {reactiveUI.Version}"); - var helpers = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "ReactiveUI.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault(); + LogInfo?.Invoke($"{reactiveUI.Name} {reactiveUI.Version}"); + var helpers = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault(); if (helpers == null) { - LogInfo("Could not find assembly: ReactiveUI.Fody.Helpers (" + string.Join(", ", ModuleDefinition.AssemblyReferences.Select(x => x.Name)) + ")"); + LogInfo?.Invoke("Could not find assembly: ReactiveUI.Fody.Helpers (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")"); return; } - LogInfo($"{helpers.Name} {helpers.Version}"); + LogInfo?.Invoke($"{helpers.Name} {helpers.Version}"); var reactiveObject = new TypeReference("ReactiveUI", "IReactiveObject", ModuleDefinition, reactiveUI); var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType != null && reactiveObject.IsAssignableFrom(x.BaseType)).ToArray(); @@ -77,13 +77,13 @@ public void Execute() throw new Exception("reactiveObjectExtensions is null"); } - var raisePropertyChangedMethod = ModuleDefinition.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaisePropertyChanged")); + var raisePropertyChangedMethod = ModuleDefinition?.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaisePropertyChanged")); if (raisePropertyChangedMethod == null) { throw new Exception("raisePropertyChangedMethod is null"); } - var reactiveDependencyAttribute = ModuleDefinition.FindType("ReactiveUI.Fody.Helpers", "ReactiveDependencyAttribute", helpers); + var reactiveDependencyAttribute = ModuleDefinition?.FindType("ReactiveUI.Fody.Helpers", "ReactiveDependencyAttribute", helpers); if (reactiveDependencyAttribute == null) { throw new Exception("reactiveDecoratorAttribute is null"); @@ -96,7 +96,7 @@ public void Execute() // If the property already has a body then do not weave to prevent loss of instructions if (!facadeProperty.GetMethod.Body.Instructions.Any(x => x.Operand is FieldReference) || facadeProperty.GetMethod.Body.HasVariables) { - LogError($"Property {facadeProperty.Name} is not an auto property and therefore not suitable for ReactiveDependency weaving"); + LogError?.Invoke($"Property {facadeProperty.Name} is not an auto property and therefore not suitable for ReactiveDependency weaving"); continue; } @@ -106,13 +106,13 @@ public void Execute() var targetValue = targetNamedArgument.Value?.ToString(); if (string.IsNullOrEmpty(targetValue)) { - LogError("No target property defined on the object"); + LogError?.Invoke("No target property defined on the object"); continue; } if (targetType.Properties.All(x => x.Name != targetValue) && targetType.Fields.All(x => x.Name != targetValue)) { - LogError($"dependency object property/field name '{targetValue}' not found on target type {targetType.Name}"); + LogError?.Invoke($"dependency object property/field name '{targetValue}' not found on target type {targetType.Name}"); continue; } @@ -125,7 +125,7 @@ public void Execute() if (objDependencyTargetType == null) { - LogError("Couldn't result the dependency type"); + LogError?.Invoke("Couldn't result the dependency type"); continue; } @@ -141,7 +141,7 @@ public void Execute() if (objDependencyTargetType.Properties.All(x => x.Name != destinationPropertyName)) { - LogError($"Target property {destinationPropertyName} on dependency of type {objDependencyTargetType.DeclaringType.Name} not found"); + LogError?.Invoke($"Target property {destinationPropertyName} on dependency of type {objDependencyTargetType.DeclaringType.Name} not found"); continue; } @@ -150,14 +150,14 @@ public void Execute() // The property on the facade/decorator should have a setter if (facadeProperty.SetMethod == null) { - LogError($"Property {facadeProperty.DeclaringType.FullName}.{facadeProperty.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [ReactiveDecorator]"); + LogError?.Invoke($"Property {facadeProperty.DeclaringType.FullName}.{facadeProperty.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [ReactiveDecorator]"); continue; } // The property on the dependency should have a setter e.g. Dependency.SomeProperty = value; if (destinationProperty.SetMethod == null) { - LogError($"Dependency object's property {destinationProperty.DeclaringType.FullName}.{destinationProperty.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [ReactiveDecorator]"); + LogError?.Invoke($"Dependency object's property {destinationProperty.DeclaringType.FullName}.{destinationProperty.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [ReactiveDecorator]"); continue; } diff --git a/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj b/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj index 10ced0fe99..4d254be499 100644 --- a/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj +++ b/src/ReactiveUI.Fody/ReactiveUI.Fody.csproj @@ -4,6 +4,7 @@ $(TargetFrameworks);net461 Fody extension that will generate RaisePropertyChange notifications for properties and ObservableAsPropertyHelper properties False + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;xamarin;android;ios;mac;forms;monodroid;monotouch;xamarin.android;xamarin.ios;xamarin.forms;xamarin.mac;xamarin.tvos;wpf;net;netstandard;net461;uwp;tizen;unoplatform;fody; diff --git a/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs b/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs index becb51d139..9b654cff7a 100644 --- a/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs +++ b/src/ReactiveUI.Fody/ReactiveUIPropertyWeaver.cs @@ -23,7 +23,7 @@ public class ReactiveUIPropertyWeaver /// /// The module definition. /// - public ModuleDefinition ModuleDefinition { get; set; } + public ModuleDefinition? ModuleDefinition { get; set; } /// /// Gets or sets a action that will log an MessageImportance.High message to MSBuild. OPTIONAL. @@ -31,7 +31,7 @@ public class ReactiveUIPropertyWeaver /// /// The log information. /// - public Action LogInfo { get; set; } + public Action? LogInfo { get; set; } /// /// Gets or sets an action that will log an error message to MSBuild. OPTIONAL. @@ -39,7 +39,7 @@ public class ReactiveUIPropertyWeaver /// /// The log error. /// - public Action LogError { get; set; } + public Action? LogError { get; set; } /// /// Executes this property weaver. @@ -55,22 +55,22 @@ public class ReactiveUIPropertyWeaver /// public void Execute() { - var reactiveUI = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault(); + var reactiveUI = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI").OrderByDescending(x => x.Version).FirstOrDefault(); if (reactiveUI == null) { - LogInfo("Could not find assembly: ReactiveUI (" + string.Join(", ", ModuleDefinition.AssemblyReferences.Select(x => x.Name)) + ")"); + LogInfo?.Invoke("Could not find assembly: ReactiveUI (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")"); return; } - LogInfo($"{reactiveUI.Name} {reactiveUI.Version}"); - var helpers = ModuleDefinition.AssemblyReferences.Where(x => x.Name == "ReactiveUI.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault(); + LogInfo?.Invoke($"{reactiveUI.Name} {reactiveUI.Version}"); + var helpers = ModuleDefinition?.AssemblyReferences.Where(x => x.Name == "ReactiveUI.Fody.Helpers").OrderByDescending(x => x.Version).FirstOrDefault(); if (helpers == null) { - LogInfo("Could not find assembly: ReactiveUI.Fody.Helpers (" + string.Join(", ", ModuleDefinition.AssemblyReferences.Select(x => x.Name)) + ")"); + LogInfo?.Invoke("Could not find assembly: ReactiveUI.Fody.Helpers (" + string.Join(", ", ModuleDefinition?.AssemblyReferences.Select(x => x.Name)) + ")"); return; } - LogInfo($"{helpers.Name} {helpers.Version}"); + LogInfo?.Invoke($"{helpers.Name} {helpers.Version}"); var reactiveObject = new TypeReference("ReactiveUI", "IReactiveObject", ModuleDefinition, reactiveUI); var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType != null && reactiveObject.IsAssignableFrom(x.BaseType)).ToArray(); var reactiveObjectExtensions = new TypeReference("ReactiveUI", "IReactiveObjectExtensions", ModuleDefinition, reactiveUI).Resolve(); @@ -79,92 +79,95 @@ public void Execute() throw new Exception("reactiveObjectExtensions is null"); } - var raiseAndSetIfChangedMethod = ModuleDefinition.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaiseAndSetIfChanged")); + var raiseAndSetIfChangedMethod = ModuleDefinition?.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaiseAndSetIfChanged")); if (raiseAndSetIfChangedMethod == null) { throw new Exception("raiseAndSetIfChangedMethod is null"); } - var reactiveAttribute = ModuleDefinition.FindType("ReactiveUI.Fody.Helpers", "ReactiveAttribute", helpers); - if (reactiveAttribute == null) + if (ModuleDefinition != null) { - throw new Exception("reactiveAttribute is null"); - } + var reactiveAttribute = ModuleDefinition.FindType("ReactiveUI.Fody.Helpers", "ReactiveAttribute", helpers); + if (reactiveAttribute == null) + { + throw new Exception("reactiveAttribute is null"); + } - foreach (var targetType in targetTypes) - { - foreach (var property in targetType.Properties.Where(x => x.IsDefined(reactiveAttribute)).ToArray()) + foreach (var targetType in targetTypes) { - if (property.SetMethod == null) + foreach (var property in targetType.Properties.Where(x => x.IsDefined(reactiveAttribute)).ToArray()) { - LogError($"Property {property.DeclaringType.FullName}.{property.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [Reactive]"); - continue; - } + if (property.SetMethod == null) + { + LogError?.Invoke($"Property {property.DeclaringType.FullName}.{property.Name} has no setter, therefore it is not possible for the property to change, and thus should not be marked with [Reactive]"); + continue; + } - // Declare a field to store the property value - var field = new FieldDefinition("$" + property.Name, FieldAttributes.Private, property.PropertyType); - targetType.Fields.Add(field); + // Declare a field to store the property value + var field = new FieldDefinition("$" + property.Name, FieldAttributes.Private, property.PropertyType); + targetType.Fields.Add(field); - // Remove old field (the generated backing field for the auto property) - var oldField = (FieldReference)property.GetMethod.Body.Instructions.Where(x => x.Operand is FieldReference).Single().Operand; - var oldFieldDefinition = oldField.Resolve(); - targetType.Fields.Remove(oldFieldDefinition); + // Remove old field (the generated backing field for the auto property) + var oldField = (FieldReference)property.GetMethod.Body.Instructions.Where(x => x.Operand is FieldReference).Single().Operand; + var oldFieldDefinition = oldField.Resolve(); + targetType.Fields.Remove(oldFieldDefinition); - // See if there exists an initializer for the auto-property - var constructors = targetType.Methods.Where(x => x.IsConstructor); - foreach (var constructor in constructors) - { - var fieldAssignment = constructor.Body.Instructions.SingleOrDefault(x => Equals(x.Operand, oldFieldDefinition) || Equals(x.Operand, oldField)); - if (fieldAssignment != null) + // See if there exists an initializer for the auto-property + var constructors = targetType.Methods.Where(x => x.IsConstructor); + foreach (var constructor in constructors) { - // Replace field assignment with a property set (the stack semantics are the same for both, - // so happily we don't have to manipulate the bytecode any further.) - var setterCall = constructor.Body.GetILProcessor().Create(property.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, property.SetMethod); - constructor.Body.GetILProcessor().Replace(fieldAssignment, setterCall); + var fieldAssignment = constructor.Body.Instructions.SingleOrDefault(x => Equals(x.Operand, oldFieldDefinition) || Equals(x.Operand, oldField)); + if (fieldAssignment != null) + { + // Replace field assignment with a property set (the stack semantics are the same for both, + // so happily we don't have to manipulate the bytecode any further.) + var setterCall = constructor.Body.GetILProcessor().Create(property.SetMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, property.SetMethod); + constructor.Body.GetILProcessor().Replace(fieldAssignment, setterCall); + } } - } - // Build out the getter which simply returns the value of the generated field - property.GetMethod.Body = new MethodBody(property.GetMethod); - property.GetMethod.Body.Emit(il => - { - il.Emit(OpCodes.Ldarg_0); // this - il.Emit(OpCodes.Ldfld, field.BindDefinition(targetType)); // pop -> this.$PropertyName - il.Emit(OpCodes.Ret); // Return the field value that is lying on the stack - }); + // Build out the getter which simply returns the value of the generated field + property.GetMethod.Body = new MethodBody(property.GetMethod); + property.GetMethod.Body.Emit(il => + { + il.Emit(OpCodes.Ldarg_0); // this + il.Emit(OpCodes.Ldfld, field.BindDefinition(targetType)); // pop -> this.$PropertyName + il.Emit(OpCodes.Ret); // Return the field value that is lying on the stack + }); - TypeReference genericTargetType = targetType; - if (targetType.HasGenericParameters) - { - var genericDeclaration = new GenericInstanceType(targetType); - foreach (var parameter in targetType.GenericParameters) + TypeReference genericTargetType = targetType; + if (targetType.HasGenericParameters) { - genericDeclaration.GenericArguments.Add(parameter); + var genericDeclaration = new GenericInstanceType(targetType); + foreach (var parameter in targetType.GenericParameters) + { + genericDeclaration.GenericArguments.Add(parameter); + } + + genericTargetType = genericDeclaration; } - genericTargetType = genericDeclaration; - } + var methodReference = raiseAndSetIfChangedMethod.MakeGenericMethod(genericTargetType, property.PropertyType); - var methodReference = raiseAndSetIfChangedMethod.MakeGenericMethod(genericTargetType, property.PropertyType); + // Build out the setter which fires the RaiseAndSetIfChanged method + if (property.SetMethod == null) + { + throw new Exception("[Reactive] is decorating " + property.DeclaringType.FullName + "." + property.Name + ", but the property has no setter so there would be nothing to react to. Consider removing the attribute."); + } - // Build out the setter which fires the RaiseAndSetIfChanged method - if (property.SetMethod == null) - { - throw new Exception("[Reactive] is decorating " + property.DeclaringType.FullName + "." + property.Name + ", but the property has no setter so there would be nothing to react to. Consider removing the attribute."); + property.SetMethod.Body = new MethodBody(property.SetMethod); + property.SetMethod.Body.Emit(il => + { + il.Emit(OpCodes.Ldarg_0); // this + il.Emit(OpCodes.Ldarg_0); // this + il.Emit(OpCodes.Ldflda, field.BindDefinition(targetType)); // pop -> this.$PropertyName + il.Emit(OpCodes.Ldarg_1); // value + il.Emit(OpCodes.Ldstr, property.Name); // "PropertyName" + il.Emit(OpCodes.Call, methodReference); // pop * 4 -> this.RaiseAndSetIfChanged(this.$PropertyName, value, "PropertyName") + il.Emit(OpCodes.Pop); // We don't care about the result of RaiseAndSetIfChanged, so pop it off the stack (stack is now empty) + il.Emit(OpCodes.Ret); // Return out of the function + }); } - - property.SetMethod.Body = new MethodBody(property.SetMethod); - property.SetMethod.Body.Emit(il => - { - il.Emit(OpCodes.Ldarg_0); // this - il.Emit(OpCodes.Ldarg_0); // this - il.Emit(OpCodes.Ldflda, field.BindDefinition(targetType)); // pop -> this.$PropertyName - il.Emit(OpCodes.Ldarg_1); // value - il.Emit(OpCodes.Ldstr, property.Name); // "PropertyName" - il.Emit(OpCodes.Call, methodReference); // pop * 4 -> this.RaiseAndSetIfChanged(this.$PropertyName, value, "PropertyName") - il.Emit(OpCodes.Pop); // We don't care about the result of RaiseAndSetIfChanged, so pop it off the stack (stack is now empty) - il.Emit(OpCodes.Ret); // Return out of the function - }); } } } diff --git a/src/ReactiveUI.LeakTests/ReactiveUI.LeakTests.csproj b/src/ReactiveUI.LeakTests/ReactiveUI.LeakTests.csproj index 176cdf3c7e..9beaa6153c 100644 --- a/src/ReactiveUI.LeakTests/ReactiveUI.LeakTests.csproj +++ b/src/ReactiveUI.LeakTests/ReactiveUI.LeakTests.csproj @@ -1,6 +1,8 @@  - net461 + netcoreapp3.1 + $(TargetFrameworks);net461 + enable latest diff --git a/src/ReactiveUI.Splat.Tests/ReactiveUI.Splat.Tests.csproj b/src/ReactiveUI.Splat.Tests/ReactiveUI.Splat.Tests.csproj index 610fd870a1..e24830a8da 100644 --- a/src/ReactiveUI.Splat.Tests/ReactiveUI.Splat.Tests.csproj +++ b/src/ReactiveUI.Splat.Tests/ReactiveUI.Splat.Tests.csproj @@ -4,6 +4,7 @@ netcoreapp3.1 false + enable latest diff --git a/src/ReactiveUI.Testing.Tests/ReactiveUI.Testing.Tests.csproj b/src/ReactiveUI.Testing.Tests/ReactiveUI.Testing.Tests.csproj index 3b85907d75..5c364ffd7a 100644 --- a/src/ReactiveUI.Testing.Tests/ReactiveUI.Testing.Tests.csproj +++ b/src/ReactiveUI.Testing.Tests/ReactiveUI.Testing.Tests.csproj @@ -4,6 +4,7 @@ $(TargetFrameworks);net472 netstandard2.0 $(TargetFramework) + enable latest diff --git a/src/ReactiveUI.Testing.Tests/TestFixture.cs b/src/ReactiveUI.Testing.Tests/TestFixture.cs index 2e67133245..5bcd385813 100644 --- a/src/ReactiveUI.Testing.Tests/TestFixture.cs +++ b/src/ReactiveUI.Testing.Tests/TestFixture.cs @@ -21,17 +21,17 @@ public class TestFixture /// /// Gets or sets the name. /// - public string Name { get; set; } + public string? Name { get; set; } /// /// Gets or sets the tests. /// - public IEnumerable Tests { get; set; } + public IEnumerable? Tests { get; set; } /// /// Gets or sets the variables. /// [SuppressMessage("Design", "CA2227: Read only dictionary", Justification = "Used in mock.")] - public Dictionary Variables { get; set; } + public Dictionary? Variables { get; set; } } } diff --git a/src/ReactiveUI.Testing.Tests/TestFixtureBuilder.cs b/src/ReactiveUI.Testing.Tests/TestFixtureBuilder.cs index b91e86bb6b..6d2fba1814 100644 --- a/src/ReactiveUI.Testing.Tests/TestFixtureBuilder.cs +++ b/src/ReactiveUI.Testing.Tests/TestFixtureBuilder.cs @@ -13,8 +13,8 @@ namespace ReactiveUI.Testing.Tests public class TestFixtureBuilder : IBuilder { private int _count; - private string _name; - private List _tests = new List(); + private string? _name; + private List? _tests = new List(); private Dictionary _variables = new Dictionary(); /// diff --git a/src/ReactiveUI.Testing.Tests/TestFixtureBuilderExtensionTests.cs b/src/ReactiveUI.Testing.Tests/TestFixtureBuilderExtensionTests.cs index 68b061126e..0343c5e8d2 100644 --- a/src/ReactiveUI.Testing.Tests/TestFixtureBuilderExtensionTests.cs +++ b/src/ReactiveUI.Testing.Tests/TestFixtureBuilderExtensionTests.cs @@ -83,7 +83,7 @@ public void Should_Add_Key_Value(string key, string value) TestFixture builder = new TestFixtureBuilder().WithKeyValue(key, value); // Then - builder.Variables[key].ShouldBe(value); + builder.Variables?[key].ShouldBe(value); } /// @@ -98,7 +98,7 @@ public void Should_Add_Key_Value_Pair(KeyValuePair keyValuePair) TestFixture builder = new TestFixtureBuilder().WithKeyValue(keyValuePair); // Then - builder.Variables[keyValuePair.Key].ShouldBe(keyValuePair.Value); + builder.Variables?[keyValuePair.Key].ShouldBe(keyValuePair.Value); } /// diff --git a/src/ReactiveUI.Testing/IBuilderExtensions.cs b/src/ReactiveUI.Testing/IBuilderExtensions.cs index 3e98c819aa..3bae638a57 100644 --- a/src/ReactiveUI.Testing/IBuilderExtensions.cs +++ b/src/ReactiveUI.Testing/IBuilderExtensions.cs @@ -46,9 +46,9 @@ public static TBuilder With(this TBuilder builder, ref TField /// The values. /// The builder. public static TBuilder With( - this TBuilder builder, - ref List field, - IEnumerable values) + this TBuilder builder, + ref List? field, + IEnumerable values) where TBuilder : IBuilder { if (field == null) @@ -77,7 +77,7 @@ public static TBuilder With( /// The field. /// The value. /// The builder. - public static TBuilder With(this TBuilder builder, ref List field, TField value) + public static TBuilder With(this TBuilder builder, ref List? field, TField value) where TBuilder : IBuilder { if (field == null) @@ -100,10 +100,11 @@ public static TBuilder With(this TBuilder builder, ref ListThe key value pair. /// The builder. public static TBuilder With( - this TBuilder builder, - ref Dictionary dictionary, - KeyValuePair keyValuePair) + this TBuilder builder, + ref Dictionary dictionary, + KeyValuePair keyValuePair) where TBuilder : IBuilder + where TKey : notnull { if (dictionary == null) { @@ -126,11 +127,12 @@ public static TBuilder With( /// The value. /// The builder. public static TBuilder With( - this TBuilder builder, - ref Dictionary dictionary, - TKey key, - TField value) + this TBuilder builder, + ref Dictionary dictionary, + TKey key, + TField value) where TBuilder : IBuilder + where TKey : notnull { if (dictionary == null) { @@ -152,9 +154,10 @@ public static TBuilder With( /// The key value pair. /// The builder. public static TBuilder With( - this TBuilder builder, - ref Dictionary dictionary, - IDictionary keyValuePair) + this TBuilder builder, + ref Dictionary dictionary, + IDictionary keyValuePair) + where TKey : notnull { if (dictionary == null) { diff --git a/src/ReactiveUI.Testing/ReactiveUI.Testing.csproj b/src/ReactiveUI.Testing/ReactiveUI.Testing.csproj index 2625439f95..80eba9e858 100644 --- a/src/ReactiveUI.Testing/ReactiveUI.Testing.csproj +++ b/src/ReactiveUI.Testing/ReactiveUI.Testing.csproj @@ -6,6 +6,7 @@ ReactiveUI.Testing Provides extensions for testing ReactiveUI based applications ReactiveUI.Testing + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;test; diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt index 08ac4f9a59..0bbd2e99d6 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.net472.approved.txt @@ -65,15 +65,15 @@ namespace ReactiveUI } public static class CommandBinder { - public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string toEvent = null) + public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string toEvent = null) + public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string toEvent = null) + public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } @@ -81,47 +81,46 @@ namespace ReactiveUI public class CommandBinderImplementation : Splat.IEnableLogger { public CommandBinderImplementation() { } - public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Func withParameter, string toEvent = null) + public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Func withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string toEvent = null) + public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } } public static class ComparerChainingExtensions { - public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer parent, System.Func selector) { } - public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } - public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer parent, System.Func selector) { } - public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } + public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer? parent, System.Func selector) { } + public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer? parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } + public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer? parent, System.Func selector) { } + public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer? parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } } public class ComponentModelTypeConverter : ReactiveUI.IBindingTypeConverter, Splat.IEnableLogger { public ComponentModelTypeConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public bool TryConvert(object from, System.Type toType, object conversionHint, out object result) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result) { } } public class CreatesCommandBindingViaCommandParameter : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaCommandParameter() { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class CreatesCommandBindingViaEvent : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaEvent() { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public sealed class DefaultViewLocator : ReactiveUI.IViewLocator, Splat.IEnableLogger { public System.Func ViewModelToViewFunc { get; set; } - public ReactiveUI.IViewFor ResolveView(T viewModel, string contract = null) - where T : class { } + public ReactiveUI.IViewFor? ResolveView(T viewModel, string? contract = null) { } } public static class DependencyResolverMixins { @@ -139,12 +138,12 @@ namespace ReactiveUI { public EqualityTypeConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public bool TryConvert(object from, System.Type toType, object conversionHint, out object result) { } - public static object DoReferenceCast(object from, System.Type targetType) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result) { } + public static object? DoReferenceCast(object? from, System.Type targetType) { } } public static class ExpressionMixins { - public static object[] GetArgumentsArray(this System.Linq.Expressions.Expression expression) { } + public static object[]? GetArgumentsArray(this System.Linq.Expressions.Expression expression) { } public static System.Collections.Generic.IEnumerable GetExpressionChain(this System.Linq.Expressions.Expression @this) { } public static System.Reflection.MemberInfo GetMemberInfo(this System.Linq.Expressions.Expression expression) { } public static System.Linq.Expressions.Expression GetParent(this System.Linq.Expressions.Expression expression) { } @@ -162,7 +161,7 @@ namespace ReactiveUI public interface IBindingTypeConverter : Splat.IEnableLogger { int GetAffinityForObjects(System.Type fromType, System.Type toType); - bool TryConvert(object from, System.Type toType, object conversionHint, out object result); + bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result); } public interface ICanActivate { @@ -178,14 +177,14 @@ namespace ReactiveUI } public interface ICreatesCommandBinding { - System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter); - System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName); + System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter); + System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName); int GetAffinityForObject(System.Type type, bool hasEventTarget); } public interface ICreatesObservableForProperty : Splat.IEnableLogger { int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false); - System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false); + System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false); } public interface IHandleObservableErrors { @@ -193,18 +192,18 @@ namespace ReactiveUI } public interface IMessageBus : Splat.IEnableLogger { - bool IsRegistered(System.Type type, string contract = null); - System.IObservable Listen(string contract = null); - System.IObservable ListenIncludeLatest(string contract = null); - System.IDisposable RegisterMessageSource(System.IObservable source, string contract = null); - void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string contract = null); - void SendMessage(T message, string contract = null); + bool IsRegistered(System.Type type, string? contract = null); + System.IObservable Listen(string? contract = null); + System.IObservable ListenIncludeLatest(string? contract = null); + System.IDisposable RegisterMessageSource(System.IObservable source, string? contract = null); + void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string? contract = null); + void SendMessage(T message, string? contract = null); } public class INPCObservableForProperty : ReactiveUI.ICreatesObservableForProperty, Splat.IEnableLogger { public INPCObservableForProperty() { } public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged) { } - public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged, bool suppressWarnings = false) { } + public System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } } public interface IObservedChange { @@ -217,25 +216,25 @@ namespace ReactiveUI [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) + ReactiveUI.IReactiveBinding>? Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + ReactiveUI.IReactiveBinding>? Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; - System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class ; - ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) + ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; - ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; @@ -248,7 +247,7 @@ namespace ReactiveUI { public IROObservableForProperty() { } public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } - public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } + public System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } } public interface IReactiveBinding : System.IDisposable where out TView : ReactiveUI.IViewFor @@ -279,11 +278,11 @@ namespace ReactiveUI } public static class IReactiveObjectExtensions { - public static TRet RaiseAndSetIfChanged(this TObj reactiveObject, ref TRet backingField, TRet newValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + public static TRet RaiseAndSetIfChanged(this TObj reactiveObject, ref TRet backingField, TRet newValue, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TObj : ReactiveUI.IReactiveObject { } - public static void RaisePropertyChanged(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + public static void RaisePropertyChanged(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TSender : ReactiveUI.IReactiveObject { } - public static void RaisePropertyChanging(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + public static void RaisePropertyChanging(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TSender : ReactiveUI.IReactiveObject { } } public interface IReactivePropertyChangedEventArgs @@ -294,7 +293,7 @@ namespace ReactiveUI public interface IRoutableViewModel : ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging { ReactiveUI.IScreen HostScreen { get; } - string UrlPathSegment { get; } + string? UrlPathSegment { get; } } public interface IScreen { @@ -303,7 +302,7 @@ namespace ReactiveUI public interface ISetMethodBindingConverter : Splat.IEnableLogger { int GetAffinityForObjects(System.Type fromType, System.Type toType); - object PerformSet(object toTarget, object newValue, object[] arguments); + object PerformSet(object? toTarget, object? newValue, object[]? arguments); } public interface ISuspensionDriver { @@ -313,8 +312,8 @@ namespace ReactiveUI } public interface ISuspensionHost : ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging { - object AppState { get; set; } - System.Func CreateNewAppState { get; set; } + object? AppState { get; set; } + System.Func? CreateNewAppState { get; set; } System.IObservable IsLaunchingNew { get; set; } System.IObservable IsResuming { get; set; } System.IObservable IsUnpausing { get; set; } @@ -323,7 +322,7 @@ namespace ReactiveUI } public interface IViewFor : ReactiveUI.IActivatableView { - object ViewModel { get; set; } + object? ViewModel { get; set; } } public interface IViewFor : ReactiveUI.IActivatableView, ReactiveUI.IViewFor where T : class @@ -332,8 +331,7 @@ namespace ReactiveUI } public interface IViewLocator : Splat.IEnableLogger { - ReactiveUI.IViewFor ResolveView(T viewModel, string contract = null) - where T : class; + ReactiveUI.IViewFor? ResolveView(T viewModel, string? contract = null); } public sealed class InteractionContext { @@ -344,7 +342,7 @@ namespace ReactiveUI } public class Interaction { - public Interaction(System.Reactive.Concurrency.IScheduler handlerScheduler = null) { } + public Interaction(System.Reactive.Concurrency.IScheduler? handlerScheduler = null) { } protected System.Func<, >[] GetHandlers() { } public virtual System.IObservable Handle(TInput input) { } public System.IDisposable RegisterHandler(System.Action> handler) { } @@ -355,41 +353,41 @@ namespace ReactiveUI { public MessageBus() { } public static ReactiveUI.IMessageBus Current { get; set; } - public bool IsRegistered(System.Type type, string contract = null) { } - public System.IObservable Listen(string contract = null) { } - public System.IObservable ListenIncludeLatest(string contract = null) { } - public System.IDisposable RegisterMessageSource(System.IObservable source, string contract = null) { } - public void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string contract = null) { } - public void SendMessage(T message, string contract = null) { } + public bool IsRegistered(System.Type type, string? contract = null) { } + public System.IObservable Listen(string? contract = null) { } + public System.IObservable ListenIncludeLatest(string? contract = null) { } + public System.IDisposable RegisterMessageSource(System.IObservable source, string? contract = null) { } + public void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string? contract = null) { } + public void SendMessage(T message, string? contract = null) { } } public static class OAPHCreationHelperMixin { - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } } public sealed class ObservableAsPropertyHelper : ReactiveUI.IHandleObservableErrors, Splat.IEnableLogger, System.IDisposable { - public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) { } - public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, System.Action onChanging = null, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) { } + public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) { } + public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, System.Action? onChanging = null, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) { } public bool IsSubscribed { get; } public System.IObservable ThrownExceptions { get; } public T Value { get; } public void Dispose() { } - public static ReactiveUI.ObservableAsPropertyHelper Default(T initialValue = default, System.Reactive.Concurrency.IScheduler scheduler = null) { } + public static ReactiveUI.ObservableAsPropertyHelper Default(T initialValue = default, System.Reactive.Concurrency.IScheduler? scheduler = null) { } } public static class ObservableLoggingMixin { - public static System.IObservable Log(this System.IObservable @this, TObj klass, string message = null, System.Func stringifier = null) + public static System.IObservable Log(this System.IObservable @this, TObj klass, string? message = null, System.Func? stringifier = null) where TObj : Splat.IEnableLogger { } - public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.IObservable next = null, string message = null) + public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.IObservable? next = null, string? message = null) where TObj : Splat.IEnableLogger { } - public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.Func> next, string message = null) + public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.Func> next, string? message = null) where TObj : Splat.IEnableLogger where TException : System.Exception { } } @@ -422,7 +420,7 @@ namespace ReactiveUI { public POCOObservableForProperty() { } public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } - public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } + public System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } } public class PlatformRegistrations { @@ -435,21 +433,21 @@ namespace ReactiveUI [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) + public ReactiveUI.IReactiveBinding>? Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + public ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class { } - public ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) + public ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } } @@ -458,53 +456,53 @@ namespace ReactiveUI [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func vmToViewConverter, System.Func viewToVmConverter) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public static System.IDisposable BindTo(this System.IObservable @this, TTarget target, System.Linq.Expressions.Expression> property, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public static System.IDisposable BindTo(this System.IObservable @this, TTarget target, System.Linq.Expressions.Expression> property, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class { } - public static ReactiveUI.IReactiveBinding OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) + public static ReactiveUI.IReactiveBinding? OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public static ReactiveUI.IReactiveBinding OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public static ReactiveUI.IReactiveBinding? OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } } public static class ReactiveCommand { - public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.CombinedReactiveCommand CreateCombined(System.Collections.Generic.IEnumerable> childCommands, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.CombinedReactiveCommand CreateCombined(System.Collections.Generic.IEnumerable> childCommands, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } } public abstract class ReactiveCommandBase : ReactiveUI.IHandleObservableErrors, ReactiveUI.IReactiveCommand, System.IDisposable, System.IObservable, System.Windows.Input.ICommand { @@ -516,7 +514,7 @@ namespace ReactiveUI protected abstract void Dispose(bool disposing); public abstract System.IObservable Execute(TParam parameter = default); protected virtual bool ICommandCanExecute(object parameter) { } - protected virtual void ICommandExecute(object parameter) { } + protected virtual void ICommandExecute(object? parameter) { } protected void OnCanExecuteChanged(bool newValue) { } public abstract System.IDisposable Subscribe(System.IObserver observer); } @@ -531,7 +529,7 @@ namespace ReactiveUI } public class ReactiveCommand : ReactiveUI.ReactiveCommandBase { - protected ReactiveCommand(System.Func> execute, System.IObservable canExecute, System.Reactive.Concurrency.IScheduler outputScheduler) { } + protected ReactiveCommand(System.Func> execute, System.IObservable? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { } public override System.IObservable CanExecute { get; } public override System.IObservable IsExecuting { get; } public override System.IObservable ThrownExceptions { get; } @@ -576,17 +574,17 @@ namespace ReactiveUI { public static string ExpressionToPropertyNames(System.Linq.Expressions.Expression expression) { } public static System.Type GetEventArgsTypeForEvent(System.Type type, string eventName) { } - public static System.Func GetValueFetcherForProperty(System.Reflection.MemberInfo member) { } - public static System.Func GetValueFetcherOrThrow(System.Reflection.MemberInfo member) { } - public static System.Action GetValueSetterForProperty(System.Reflection.MemberInfo member) { } - public static System.Action GetValueSetterOrThrow(System.Reflection.MemberInfo member) { } + public static System.Func? GetValueFetcherForProperty(System.Reflection.MemberInfo member) { } + public static System.Func GetValueFetcherOrThrow(System.Reflection.MemberInfo member) { } + public static System.Action GetValueSetterForProperty(System.Reflection.MemberInfo member) { } + public static System.Action? GetValueSetterOrThrow(System.Reflection.MemberInfo member) { } public static bool IsStatic(this System.Reflection.PropertyInfo item) { } - public static System.Type ReallyFindType(string type, bool throwOnFailure) { } + public static System.Type? ReallyFindType(string? type, bool throwOnFailure) { } public static System.Linq.Expressions.Expression Rewrite(System.Linq.Expressions.Expression expression) { } public static void ThrowIfMethodsNotOverloaded(string callingTypeName, object targetObject, params string[] methodsToCheck) { } - public static bool TryGetAllValuesForPropertyChain(out ReactiveUI.IObservedChange<, >[] changeValues, object current, System.Collections.Generic.IEnumerable expressionChain) { } - public static bool TryGetValueForPropertyChain(out TValue changeValue, object current, System.Collections.Generic.IEnumerable expressionChain) { } - public static bool TrySetValueToPropertyChain(object target, System.Collections.Generic.IEnumerable expressionChain, TValue value, bool shouldThrow = true) { } + public static bool TryGetAllValuesForPropertyChain(out ReactiveUI.IObservedChange<, >[] changeValues, object? current, System.Collections.Generic.IEnumerable expressionChain) { } + public static bool TryGetValueForPropertyChain(out TValue changeValue, object? current, System.Collections.Generic.IEnumerable expressionChain) { } + public static bool TrySetValueToPropertyChain(object? target, System.Collections.Generic.IEnumerable expressionChain, TValue value, bool shouldThrow = true) { } } public class Registrations { @@ -637,7 +635,7 @@ namespace ReactiveUI } public class ScheduledSubject : System.IDisposable, System.IObservable, System.IObserver, System.Reactive.Subjects.ISubject, System.Reactive.Subjects.ISubject { - public ScheduledSubject(System.Reactive.Concurrency.IScheduler scheduler, System.IObserver defaultObserver = null, System.Reactive.Subjects.ISubject defaultSubject = null) { } + public ScheduledSubject(System.Reactive.Concurrency.IScheduler scheduler, System.IObserver? defaultObserver = null, System.Reactive.Subjects.ISubject? defaultSubject = null) { } public void Dispose() { } protected virtual void Dispose(bool isDisposing) { } public void OnCompleted() { } @@ -654,14 +652,14 @@ namespace ReactiveUI { public StringConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public bool TryConvert(object from, System.Type toType, object conversionHint, out object result) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result) { } } public static class SuspensionHostExtensions { public static T GetAppState(this ReactiveUI.ISuspensionHost item) { } public static System.IObservable ObserveAppState(this ReactiveUI.ISuspensionHost item) where T : class { } - public static System.IDisposable SetupDefaultSuspendResume(this ReactiveUI.ISuspensionHost item, ReactiveUI.ISuspensionDriver driver = null) { } + public static System.IDisposable SetupDefaultSuspendResume(this ReactiveUI.ISuspensionHost item, ReactiveUI.ISuspensionDriver? driver = null) { } } [System.Serializable] public class UnhandledErrorException : System.Exception @@ -680,7 +678,7 @@ namespace ReactiveUI protected UnhandledInteractionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public UnhandledInteractionException(string message, System.Exception innerException) { } public TInput Input { get; } - public ReactiveUI.Interaction Interaction { get; } + public ReactiveUI.Interaction? Interaction { get; } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.All)] @@ -697,8 +695,8 @@ namespace ReactiveUI public static void WhenActivated(this ReactiveUI.IActivatableViewModel item, System.Action block) { } public static void WhenActivated(this ReactiveUI.IActivatableViewModel item, System.Func> block) { } public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Action> block, ReactiveUI.IViewFor view) { } - public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Action block, ReactiveUI.IViewFor view = null) { } - public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Func> block, ReactiveUI.IViewFor view) { } + public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Action block, ReactiveUI.IViewFor? view = null) { } + public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Func> block, ReactiveUI.IViewFor? view) { } } public static class ViewLocator { 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 f298b5851a..48be053cf6 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.ReactiveUI.netcoreapp3.1.approved.txt @@ -65,15 +65,15 @@ namespace ReactiveUI } public static class CommandBinder { - public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string toEvent = null) + public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string toEvent = null) + public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.IObservable withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string toEvent = null) + public static ReactiveUI.IReactiveBinding BindCommand(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> propertyName, System.Linq.Expressions.Expression> controlName, System.Linq.Expressions.Expression> withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } @@ -81,47 +81,46 @@ namespace ReactiveUI public class CommandBinderImplementation : Splat.IEnableLogger { public CommandBinderImplementation() { } - public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Func withParameter, string toEvent = null) + public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.Func withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } - public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string toEvent = null) + public ReactiveUI.IReactiveBinding BindCommand(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> controlProperty, System.IObservable withParameter, string? toEvent = null) where TView : class, ReactiveUI.IViewFor where TViewModel : class where TProp : System.Windows.Input.ICommand { } } public static class ComparerChainingExtensions { - public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer parent, System.Func selector) { } - public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } - public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer parent, System.Func selector) { } - public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } + public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer? parent, System.Func selector) { } + public static System.Collections.Generic.IComparer ThenBy(this System.Collections.Generic.IComparer? parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } + public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer? parent, System.Func selector) { } + public static System.Collections.Generic.IComparer ThenByDescending(this System.Collections.Generic.IComparer? parent, System.Func selector, System.Collections.Generic.IComparer comparer) { } } public class ComponentModelTypeConverter : ReactiveUI.IBindingTypeConverter, Splat.IEnableLogger { public ComponentModelTypeConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public bool TryConvert(object from, System.Type toType, object conversionHint, out object result) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result) { } } public class CreatesCommandBindingViaCommandParameter : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaCommandParameter() { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class CreatesCommandBindingViaEvent : ReactiveUI.ICreatesCommandBinding { public CreatesCommandBindingViaEvent() { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public sealed class DefaultViewLocator : ReactiveUI.IViewLocator, Splat.IEnableLogger { public System.Func ViewModelToViewFunc { get; set; } - public ReactiveUI.IViewFor ResolveView(T viewModel, string contract = null) - where T : class { } + public ReactiveUI.IViewFor? ResolveView(T viewModel, string? contract = null) { } } public static class DependencyResolverMixins { @@ -139,12 +138,12 @@ namespace ReactiveUI { public EqualityTypeConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public bool TryConvert(object from, System.Type toType, object conversionHint, out object result) { } - public static object DoReferenceCast(object from, System.Type targetType) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result) { } + public static object? DoReferenceCast(object? from, System.Type targetType) { } } public static class ExpressionMixins { - public static object[] GetArgumentsArray(this System.Linq.Expressions.Expression expression) { } + public static object[]? GetArgumentsArray(this System.Linq.Expressions.Expression expression) { } public static System.Collections.Generic.IEnumerable GetExpressionChain(this System.Linq.Expressions.Expression @this) { } public static System.Reflection.MemberInfo GetMemberInfo(this System.Linq.Expressions.Expression expression) { } public static System.Linq.Expressions.Expression GetParent(this System.Linq.Expressions.Expression expression) { } @@ -162,7 +161,7 @@ namespace ReactiveUI public interface IBindingTypeConverter : Splat.IEnableLogger { int GetAffinityForObjects(System.Type fromType, System.Type toType); - bool TryConvert(object from, System.Type toType, object conversionHint, out object result); + bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result); } public interface ICanActivate { @@ -178,14 +177,14 @@ namespace ReactiveUI } public interface ICreatesCommandBinding { - System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter); - System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName); + System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter); + System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName); int GetAffinityForObject(System.Type type, bool hasEventTarget); } public interface ICreatesObservableForProperty : Splat.IEnableLogger { int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false); - System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false); + System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false); } public interface IHandleObservableErrors { @@ -193,18 +192,18 @@ namespace ReactiveUI } public interface IMessageBus : Splat.IEnableLogger { - bool IsRegistered(System.Type type, string contract = null); - System.IObservable Listen(string contract = null); - System.IObservable ListenIncludeLatest(string contract = null); - System.IDisposable RegisterMessageSource(System.IObservable source, string contract = null); - void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string contract = null); - void SendMessage(T message, string contract = null); + bool IsRegistered(System.Type type, string? contract = null); + System.IObservable Listen(string? contract = null); + System.IObservable ListenIncludeLatest(string? contract = null); + System.IDisposable RegisterMessageSource(System.IObservable source, string? contract = null); + void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string? contract = null); + void SendMessage(T message, string? contract = null); } public class INPCObservableForProperty : ReactiveUI.ICreatesObservableForProperty, Splat.IEnableLogger { public INPCObservableForProperty() { } public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged) { } - public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged, bool suppressWarnings = false) { } + public System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } } public interface IObservedChange { @@ -217,25 +216,25 @@ namespace ReactiveUI [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) + ReactiveUI.IReactiveBinding>? Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + ReactiveUI.IReactiveBinding>? Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; - System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class ; - ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) + ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; - ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor ; @@ -248,7 +247,7 @@ namespace ReactiveUI { public IROObservableForProperty() { } public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } - public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } + public System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } } public interface IReactiveBinding : System.IDisposable where out TView : ReactiveUI.IViewFor @@ -279,11 +278,11 @@ namespace ReactiveUI } public static class IReactiveObjectExtensions { - public static TRet RaiseAndSetIfChanged(this TObj reactiveObject, ref TRet backingField, TRet newValue, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + public static TRet RaiseAndSetIfChanged(this TObj reactiveObject, ref TRet backingField, TRet newValue, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TObj : ReactiveUI.IReactiveObject { } - public static void RaisePropertyChanged(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + public static void RaisePropertyChanged(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TSender : ReactiveUI.IReactiveObject { } - public static void RaisePropertyChanging(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) + public static void RaisePropertyChanging(this TSender reactiveObject, [System.Runtime.CompilerServices.CallerMemberName] string? propertyName = null) where TSender : ReactiveUI.IReactiveObject { } } public interface IReactivePropertyChangedEventArgs @@ -294,7 +293,7 @@ namespace ReactiveUI public interface IRoutableViewModel : ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging { ReactiveUI.IScreen HostScreen { get; } - string UrlPathSegment { get; } + string? UrlPathSegment { get; } } public interface IScreen { @@ -303,7 +302,7 @@ namespace ReactiveUI public interface ISetMethodBindingConverter : Splat.IEnableLogger { int GetAffinityForObjects(System.Type fromType, System.Type toType); - object PerformSet(object toTarget, object newValue, object[] arguments); + object PerformSet(object? toTarget, object? newValue, object[]? arguments); } public interface ISuspensionDriver { @@ -313,8 +312,8 @@ namespace ReactiveUI } public interface ISuspensionHost : ReactiveUI.IReactiveObject, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging { - object AppState { get; set; } - System.Func CreateNewAppState { get; set; } + object? AppState { get; set; } + System.Func? CreateNewAppState { get; set; } System.IObservable IsLaunchingNew { get; set; } System.IObservable IsResuming { get; set; } System.IObservable IsUnpausing { get; set; } @@ -323,7 +322,7 @@ namespace ReactiveUI } public interface IViewFor : ReactiveUI.IActivatableView { - object ViewModel { get; set; } + object? ViewModel { get; set; } } public interface IViewFor : ReactiveUI.IActivatableView, ReactiveUI.IViewFor where T : class @@ -332,8 +331,7 @@ namespace ReactiveUI } public interface IViewLocator : Splat.IEnableLogger { - ReactiveUI.IViewFor ResolveView(T viewModel, string contract = null) - where T : class; + ReactiveUI.IViewFor? ResolveView(T viewModel, string? contract = null); } public sealed class InteractionContext { @@ -344,7 +342,7 @@ namespace ReactiveUI } public class Interaction { - public Interaction(System.Reactive.Concurrency.IScheduler handlerScheduler = null) { } + public Interaction(System.Reactive.Concurrency.IScheduler? handlerScheduler = null) { } protected System.Func<, >[] GetHandlers() { } public virtual System.IObservable Handle(TInput input) { } public System.IDisposable RegisterHandler(System.Action> handler) { } @@ -355,41 +353,41 @@ namespace ReactiveUI { public MessageBus() { } public static ReactiveUI.IMessageBus Current { get; set; } - public bool IsRegistered(System.Type type, string contract = null) { } - public System.IObservable Listen(string contract = null) { } - public System.IObservable ListenIncludeLatest(string contract = null) { } - public System.IDisposable RegisterMessageSource(System.IObservable source, string contract = null) { } - public void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string contract = null) { } - public void SendMessage(T message, string contract = null) { } + public bool IsRegistered(System.Type type, string? contract = null) { } + public System.IObservable Listen(string? contract = null) { } + public System.IObservable ListenIncludeLatest(string? contract = null) { } + public System.IDisposable RegisterMessageSource(System.IObservable source, string? contract = null) { } + public void RegisterScheduler(System.Reactive.Concurrency.IScheduler scheduler, string? contract = null) { } + public void SendMessage(T message, string? contract = null) { } } public static class OAPHCreationHelperMixin { - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, System.Linq.Expressions.Expression> property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } - public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) + public static ReactiveUI.ObservableAsPropertyHelper ToProperty(this System.IObservable target, TObj source, string property, out ReactiveUI.ObservableAsPropertyHelper result, TRet initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) where TObj : class, ReactiveUI.IReactiveObject { } } public sealed class ObservableAsPropertyHelper : ReactiveUI.IHandleObservableErrors, Splat.IEnableLogger, System.IDisposable { - public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) { } - public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, System.Action onChanging = null, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler scheduler = null) { } + public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) { } + public ObservableAsPropertyHelper(System.IObservable observable, System.Action onChanged, System.Action? onChanging = null, T initialValue = default, bool deferSubscription = false, System.Reactive.Concurrency.IScheduler? scheduler = null) { } public bool IsSubscribed { get; } public System.IObservable ThrownExceptions { get; } public T Value { get; } public void Dispose() { } - public static ReactiveUI.ObservableAsPropertyHelper Default(T initialValue = default, System.Reactive.Concurrency.IScheduler scheduler = null) { } + public static ReactiveUI.ObservableAsPropertyHelper Default(T initialValue = default, System.Reactive.Concurrency.IScheduler? scheduler = null) { } } public static class ObservableLoggingMixin { - public static System.IObservable Log(this System.IObservable @this, TObj klass, string message = null, System.Func stringifier = null) + public static System.IObservable Log(this System.IObservable @this, TObj klass, string? message = null, System.Func? stringifier = null) where TObj : Splat.IEnableLogger { } - public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.IObservable next = null, string message = null) + public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.IObservable? next = null, string? message = null) where TObj : Splat.IEnableLogger { } - public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.Func> next, string message = null) + public static System.IObservable LoggedCatch(this System.IObservable @this, TObj klass, System.Func> next, string? message = null) where TObj : Splat.IEnableLogger where TException : System.Exception { } } @@ -422,7 +420,7 @@ namespace ReactiveUI { public POCOObservableForProperty() { } public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } - public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } + public System.IObservable>? GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } } public class PlatformRegistrations { @@ -435,21 +433,21 @@ namespace ReactiveUI [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) + public ReactiveUI.IReactiveBinding>? Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, object conversionHint, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + public ReactiveUI.IReactiveBinding> Bind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, object? conversionHint, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public System.IDisposable BindTo(System.IObservable observedChange, TTarget target, System.Linq.Expressions.Expression> propertyExpression, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class { } - public ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) + public ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public ReactiveUI.IReactiveBinding OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public ReactiveUI.IReactiveBinding? OneWayBind(TViewModel viewModel, TView view, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } } @@ -458,53 +456,53 @@ namespace ReactiveUI [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func vmToViewConverter, System.Func viewToVmConverter) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, System.Func vmToViewConverter, System.Func viewToVmConverter) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } [return: System.Runtime.CompilerServices.TupleElementNames(new string[] { "view", "isViewModel"})] - public static ReactiveUI.IReactiveBinding> Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable signalViewUpdate, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter viewToVMConverterOverride = null) + public static ReactiveUI.IReactiveBinding>? Bind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.IObservable? signalViewUpdate, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null, ReactiveUI.IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public static System.IDisposable BindTo(this System.IObservable @this, TTarget target, System.Linq.Expressions.Expression> property, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public static System.IDisposable BindTo(this System.IObservable @this, TTarget target, System.Linq.Expressions.Expression> property, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class { } - public static ReactiveUI.IReactiveBinding OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) + public static ReactiveUI.IReactiveBinding? OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, System.Func selector) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } - public static ReactiveUI.IReactiveBinding OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object conversionHint = null, ReactiveUI.IBindingTypeConverter vmToViewConverterOverride = null) + public static ReactiveUI.IReactiveBinding? OneWayBind(this TView view, TViewModel viewModel, System.Linq.Expressions.Expression> vmProperty, System.Linq.Expressions.Expression> viewProperty, object? conversionHint = null, ReactiveUI.IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, ReactiveUI.IViewFor { } } public static class ReactiveCommand { - public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.CombinedReactiveCommand CreateCombined(System.Collections.Generic.IEnumerable> childCommands, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } - public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable canExecute = null, System.Reactive.Concurrency.IScheduler outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Action execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand Create(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.CombinedReactiveCommand CreateCombined(System.Collections.Generic.IEnumerable> childCommands, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromObservable(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } + public static ReactiveUI.ReactiveCommand CreateFromTask(System.Func> execute, System.IObservable? canExecute = null, System.Reactive.Concurrency.IScheduler? outputScheduler = null) { } } public abstract class ReactiveCommandBase : ReactiveUI.IHandleObservableErrors, ReactiveUI.IReactiveCommand, System.IDisposable, System.IObservable, System.Windows.Input.ICommand { @@ -516,7 +514,7 @@ namespace ReactiveUI protected abstract void Dispose(bool disposing); public abstract System.IObservable Execute(TParam parameter = default); protected virtual bool ICommandCanExecute(object parameter) { } - protected virtual void ICommandExecute(object parameter) { } + protected virtual void ICommandExecute(object? parameter) { } protected void OnCanExecuteChanged(bool newValue) { } public abstract System.IDisposable Subscribe(System.IObserver observer); } @@ -531,7 +529,7 @@ namespace ReactiveUI } public class ReactiveCommand : ReactiveUI.ReactiveCommandBase { - protected ReactiveCommand(System.Func> execute, System.IObservable canExecute, System.Reactive.Concurrency.IScheduler outputScheduler) { } + protected ReactiveCommand(System.Func> execute, System.IObservable? canExecute, System.Reactive.Concurrency.IScheduler? outputScheduler) { } public override System.IObservable CanExecute { get; } public override System.IObservable IsExecuting { get; } public override System.IObservable ThrownExceptions { get; } @@ -576,17 +574,17 @@ namespace ReactiveUI { public static string ExpressionToPropertyNames(System.Linq.Expressions.Expression expression) { } public static System.Type GetEventArgsTypeForEvent(System.Type type, string eventName) { } - public static System.Func GetValueFetcherForProperty(System.Reflection.MemberInfo member) { } - public static System.Func GetValueFetcherOrThrow(System.Reflection.MemberInfo member) { } - public static System.Action GetValueSetterForProperty(System.Reflection.MemberInfo member) { } - public static System.Action GetValueSetterOrThrow(System.Reflection.MemberInfo member) { } + public static System.Func? GetValueFetcherForProperty(System.Reflection.MemberInfo member) { } + public static System.Func GetValueFetcherOrThrow(System.Reflection.MemberInfo member) { } + public static System.Action GetValueSetterForProperty(System.Reflection.MemberInfo member) { } + public static System.Action? GetValueSetterOrThrow(System.Reflection.MemberInfo member) { } public static bool IsStatic(this System.Reflection.PropertyInfo item) { } - public static System.Type ReallyFindType(string type, bool throwOnFailure) { } + public static System.Type? ReallyFindType(string? type, bool throwOnFailure) { } public static System.Linq.Expressions.Expression Rewrite(System.Linq.Expressions.Expression expression) { } public static void ThrowIfMethodsNotOverloaded(string callingTypeName, object targetObject, params string[] methodsToCheck) { } - public static bool TryGetAllValuesForPropertyChain(out ReactiveUI.IObservedChange<, >[] changeValues, object current, System.Collections.Generic.IEnumerable expressionChain) { } - public static bool TryGetValueForPropertyChain(out TValue changeValue, object current, System.Collections.Generic.IEnumerable expressionChain) { } - public static bool TrySetValueToPropertyChain(object target, System.Collections.Generic.IEnumerable expressionChain, TValue value, bool shouldThrow = true) { } + public static bool TryGetAllValuesForPropertyChain(out ReactiveUI.IObservedChange<, >[] changeValues, object? current, System.Collections.Generic.IEnumerable expressionChain) { } + public static bool TryGetValueForPropertyChain(out TValue changeValue, object? current, System.Collections.Generic.IEnumerable expressionChain) { } + public static bool TrySetValueToPropertyChain(object? target, System.Collections.Generic.IEnumerable expressionChain, TValue value, bool shouldThrow = true) { } } public class Registrations { @@ -637,7 +635,7 @@ namespace ReactiveUI } public class ScheduledSubject : System.IDisposable, System.IObservable, System.IObserver, System.Reactive.Subjects.ISubject, System.Reactive.Subjects.ISubject { - public ScheduledSubject(System.Reactive.Concurrency.IScheduler scheduler, System.IObserver defaultObserver = null, System.Reactive.Subjects.ISubject defaultSubject = null) { } + public ScheduledSubject(System.Reactive.Concurrency.IScheduler scheduler, System.IObserver? defaultObserver = null, System.Reactive.Subjects.ISubject? defaultSubject = null) { } public void Dispose() { } protected virtual void Dispose(bool isDisposing) { } public void OnCompleted() { } @@ -654,14 +652,14 @@ namespace ReactiveUI { public StringConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public bool TryConvert(object from, System.Type toType, object conversionHint, out object result) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object? result) { } } public static class SuspensionHostExtensions { public static T GetAppState(this ReactiveUI.ISuspensionHost item) { } public static System.IObservable ObserveAppState(this ReactiveUI.ISuspensionHost item) where T : class { } - public static System.IDisposable SetupDefaultSuspendResume(this ReactiveUI.ISuspensionHost item, ReactiveUI.ISuspensionDriver driver = null) { } + public static System.IDisposable SetupDefaultSuspendResume(this ReactiveUI.ISuspensionHost item, ReactiveUI.ISuspensionDriver? driver = null) { } } [System.Serializable] public class UnhandledErrorException : System.Exception @@ -680,7 +678,7 @@ namespace ReactiveUI protected UnhandledInteractionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } public UnhandledInteractionException(string message, System.Exception innerException) { } public TInput Input { get; } - public ReactiveUI.Interaction Interaction { get; } + public ReactiveUI.Interaction? Interaction { get; } public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { } } [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.All)] @@ -697,8 +695,8 @@ namespace ReactiveUI public static void WhenActivated(this ReactiveUI.IActivatableViewModel item, System.Action block) { } public static void WhenActivated(this ReactiveUI.IActivatableViewModel item, System.Func> block) { } public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Action> block, ReactiveUI.IViewFor view) { } - public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Action block, ReactiveUI.IViewFor view = null) { } - public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Func> block, ReactiveUI.IViewFor view) { } + public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Action block, ReactiveUI.IViewFor? view = null) { } + public static System.IDisposable WhenActivated(this ReactiveUI.IActivatableView item, System.Func> block, ReactiveUI.IViewFor? view) { } } public static class ViewLocator { diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.net472.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.net472.approved.txt index bacce2766b..95c44eddea 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.net472.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.net472.approved.txt @@ -4,17 +4,20 @@ namespace ReactiveUI.Testing public interface IBuilder { } public static class IBuilderExtensions { - public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List field, System.Collections.Generic.IEnumerable values) + public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List? field, System.Collections.Generic.IEnumerable values) where TBuilder : ReactiveUI.Testing.IBuilder { } - public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List field, TField value) + public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List? field, TField value) where TBuilder : ReactiveUI.Testing.IBuilder { } public static TBuilder With(this TBuilder builder, ref TField field, TField value) where TBuilder : ReactiveUI.Testing.IBuilder { } - public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, System.Collections.Generic.IDictionary keyValuePair) { } + public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, System.Collections.Generic.IDictionary keyValuePair) + where TKey : notnull { } public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, System.Collections.Generic.KeyValuePair keyValuePair) - where TBuilder : ReactiveUI.Testing.IBuilder { } + where TBuilder : ReactiveUI.Testing.IBuilder + where TKey : notnull { } public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, TKey key, TField value) - where TBuilder : ReactiveUI.Testing.IBuilder { } + where TBuilder : ReactiveUI.Testing.IBuilder + where TKey : notnull { } } public static class MessageBusExtensions { diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.netcoreapp3.1.approved.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.netcoreapp3.1.approved.txt index 13761a893b..ed5890e0cd 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.netcoreapp3.1.approved.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.netcoreapp3.1.approved.txt @@ -4,17 +4,20 @@ namespace ReactiveUI.Testing public interface IBuilder { } public static class IBuilderExtensions { - public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List field, System.Collections.Generic.IEnumerable values) + public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List? field, System.Collections.Generic.IEnumerable values) where TBuilder : ReactiveUI.Testing.IBuilder { } - public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List field, TField value) + public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.List? field, TField value) where TBuilder : ReactiveUI.Testing.IBuilder { } public static TBuilder With(this TBuilder builder, ref TField field, TField value) where TBuilder : ReactiveUI.Testing.IBuilder { } - public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, System.Collections.Generic.IDictionary keyValuePair) { } + public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, System.Collections.Generic.IDictionary keyValuePair) + where TKey : notnull { } public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, System.Collections.Generic.KeyValuePair keyValuePair) - where TBuilder : ReactiveUI.Testing.IBuilder { } + where TBuilder : ReactiveUI.Testing.IBuilder + where TKey : notnull { } public static TBuilder With(this TBuilder builder, ref System.Collections.Generic.Dictionary dictionary, TKey key, TField value) - where TBuilder : ReactiveUI.Testing.IBuilder { } + where TBuilder : ReactiveUI.Testing.IBuilder + where TKey : notnull { } } public static class MessageBusExtensions { diff --git a/src/ReactiveUI.Tests/Activation/ActivatingView.cs b/src/ReactiveUI.Tests/Activation/ActivatingView.cs index 20040ffbd2..580042c67b 100644 --- a/src/ReactiveUI.Tests/Activation/ActivatingView.cs +++ b/src/ReactiveUI.Tests/Activation/ActivatingView.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -12,7 +12,7 @@ namespace ReactiveUI.Tests { public sealed class ActivatingView : ReactiveObject, IViewFor, IDisposable { - private ActivatingViewModel _viewModel; + private ActivatingViewModel? _viewModel; public ActivatingView() { @@ -27,16 +27,16 @@ public ActivatingView() public Subject Unloaded { get; } = new Subject(); - public ActivatingViewModel ViewModel + public ActivatingViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (ActivatingViewModel)value; + set => ViewModel = (ActivatingViewModel?)value; } public int IsActiveCount { get; set; } diff --git a/src/ReactiveUI.Tests/Activation/ActivatingViewFetcher.cs b/src/ReactiveUI.Tests/Activation/ActivatingViewFetcher.cs index 316abeb5be..18578cca76 100644 --- a/src/ReactiveUI.Tests/Activation/ActivatingViewFetcher.cs +++ b/src/ReactiveUI.Tests/Activation/ActivatingViewFetcher.cs @@ -19,6 +19,12 @@ public int GetAffinityForView(Type view) public IObservable GetActivationForView(IActivatableView view) { var av = view as ActivatingView; + + if (av == null) + { + throw new ArgumentNullException(nameof(view)); + } + return av.Loaded.Select(_ => true).Merge(av.Unloaded.Select(_ => false)); } } diff --git a/src/ReactiveUI.Tests/Activation/CanActivateViewFetcherTests.cs b/src/ReactiveUI.Tests/Activation/CanActivateViewFetcherTests.cs index a8c35cf51f..04fb9683da 100644 --- a/src/ReactiveUI.Tests/Activation/CanActivateViewFetcherTests.cs +++ b/src/ReactiveUI.Tests/Activation/CanActivateViewFetcherTests.cs @@ -5,6 +5,8 @@ using System; using System.Reactive; +using System.Reactive.Linq; + using Xunit; namespace ReactiveUI.Tests @@ -38,9 +40,9 @@ public void ReturnsZeroForNonICanActivateDerivatives() #pragma warning disable CA1812 // Class is not instantiated private class CanActivateStub : ICanActivate { - public IObservable Activated { get; } + public IObservable Activated { get; } = Observable.Empty(); - public IObservable Deactivated { get; } + public IObservable Deactivated { get; } = Observable.Empty(); } } } diff --git a/src/ReactiveUI.Tests/Commands/CombinedReactiveCommandTest.cs b/src/ReactiveUI.Tests/Commands/CombinedReactiveCommandTest.cs index 55d758a8f0..fc08d72256 100644 --- a/src/ReactiveUI.Tests/Commands/CombinedReactiveCommandTest.cs +++ b/src/ReactiveUI.Tests/Commands/CombinedReactiveCommandTest.cs @@ -84,7 +84,7 @@ public void ExceptionsAreDeliveredOnOutputScheduler() var child = ReactiveCommand.CreateFromObservable(() => Observable.Throw(new InvalidOperationException("oops"))); var childCommands = new[] { child }; var fixture = ReactiveCommand.CreateCombined(childCommands, outputScheduler: sched); - Exception exception = null; + Exception? exception = null; fixture.ThrownExceptions.Subscribe(ex => exception = ex); fixture.Execute().Subscribe(_ => { }, _ => { }); diff --git a/src/ReactiveUI.Tests/Commands/Mocks/FakeCommand.cs b/src/ReactiveUI.Tests/Commands/Mocks/FakeCommand.cs index 831ddd7c48..d210f50b07 100644 --- a/src/ReactiveUI.Tests/Commands/Mocks/FakeCommand.cs +++ b/src/ReactiveUI.Tests/Commands/Mocks/FakeCommand.cs @@ -10,7 +10,13 @@ namespace ReactiveUI.Tests { public class FakeCommand : ICommand { - public event EventHandler CanExecuteChanged; + public FakeCommand() + { + CanExecuteParameter = default!; + ExecuteParameter = default!; + } + + public event EventHandler CanExecuteChanged = null!; public object CanExecuteParameter { get; private set; } diff --git a/src/ReactiveUI.Tests/Commands/Mocks/ICommandHolder.cs b/src/ReactiveUI.Tests/Commands/Mocks/ICommandHolder.cs index b0a82713d9..609284b3bf 100644 --- a/src/ReactiveUI.Tests/Commands/Mocks/ICommandHolder.cs +++ b/src/ReactiveUI.Tests/Commands/Mocks/ICommandHolder.cs @@ -9,12 +9,12 @@ namespace ReactiveUI.Tests { public class ICommandHolder : ReactiveObject { - private ICommand _theCommand; + private ICommand? _theCommand; - public ICommand TheCommand + public ICommand? TheCommand { get => _theCommand; set => this.RaiseAndSetIfChanged(ref _theCommand, value); } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Commands/Mocks/ReactiveCommandHolder.cs b/src/ReactiveUI.Tests/Commands/Mocks/ReactiveCommandHolder.cs index 5dee36dd1a..f527a67675 100644 --- a/src/ReactiveUI.Tests/Commands/Mocks/ReactiveCommandHolder.cs +++ b/src/ReactiveUI.Tests/Commands/Mocks/ReactiveCommandHolder.cs @@ -9,9 +9,9 @@ namespace ReactiveUI.Tests { public class ReactiveCommandHolder : ReactiveObject { - private ReactiveCommand _theCommand; + private ReactiveCommand? _theCommand; - public ReactiveCommand TheCommand + public ReactiveCommand? TheCommand { get => _theCommand; set => this.RaiseAndSetIfChanged(ref _theCommand, value); diff --git a/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs b/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs index 586c636a76..aba9dc6ee9 100644 --- a/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs +++ b/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs @@ -179,6 +179,8 @@ public void CreateTaskFacilitatesTPLIntegrationWithParameter() [Fact] public void CreateThrowsIfExecutionParameterIsNull() { +#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. Assert.Throws(() => ReactiveCommand.Create(null)); Assert.Throws(() => ReactiveCommand.Create((Func)null)); Assert.Throws(() => ReactiveCommand.Create((Action)null)); @@ -187,6 +189,8 @@ public void CreateThrowsIfExecutionParameterIsNull() Assert.Throws(() => ReactiveCommand.Create((Func>)null)); Assert.Throws(() => ReactiveCommand.Create((Func>)null)); Assert.Throws(() => ReactiveCommand.Create((Func>)null)); +#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. +#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } [Fact] @@ -196,7 +200,7 @@ public void ExceptionsAreDeliveredOnOutputScheduler() scheduler => { ReactiveCommand fixture = ReactiveCommand.CreateFromObservable(() => Observable.Throw(new InvalidOperationException()), outputScheduler: scheduler); - Exception exception = null; + Exception? exception = null; fixture.ThrownExceptions.Subscribe(ex => exception = ex); fixture.Execute().Subscribe(_ => { }, _ => { }); @@ -359,7 +363,7 @@ public void ExecuteTicksAnyException() { ReactiveCommand fixture = ReactiveCommand.CreateFromObservable(() => Observable.Throw(new InvalidOperationException()), outputScheduler: ImmediateScheduler.Instance); fixture.ThrownExceptions.Subscribe(); - Exception exception = null; + Exception? exception = null; fixture.Execute().Subscribe(_ => { }, ex => exception = ex, () => { }); Assert.IsType(exception); @@ -370,7 +374,7 @@ public void ExecuteTicksAnyLambdaException() { ReactiveCommand fixture = ReactiveCommand.CreateFromObservable(() => throw new InvalidOperationException(), outputScheduler: ImmediateScheduler.Instance); fixture.ThrownExceptions.Subscribe(); - Exception exception = null; + Exception? exception = null; fixture.Execute().Subscribe(_ => { }, ex => exception = ex, () => { }); Assert.IsType(exception); @@ -452,7 +456,7 @@ public void InvokeCommandAgainstICommandInTargetInvokesTheCommand() int executionCount = 0; ICommandHolder fixture = new ICommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); fixture.TheCommand = ReactiveCommand.Create(() => ++executionCount, outputScheduler: ImmediateScheduler.Instance); source.OnNext(Unit.Default); @@ -467,7 +471,7 @@ public void InvokeCommandAgainstICommandInTargetPassesTheSpecifiedValueToCanExec { ICommandHolder fixture = new ICommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x!.TheCommand!); FakeCommand command = new FakeCommand(); fixture.TheCommand = command; @@ -483,7 +487,7 @@ public void InvokeCommandAgainstICommandInTargetRespectsCanExecute() BehaviorSubject canExecute = new BehaviorSubject(false); ICommandHolder fixture = new ICommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); fixture.TheCommand = ReactiveCommand.Create(() => executed = true, canExecute, ImmediateScheduler.Instance); source.OnNext(Unit.Default); @@ -501,7 +505,7 @@ public void InvokeCommandAgainstICommandInTargetRespectsCanExecuteWindow() BehaviorSubject canExecute = new BehaviorSubject(false); ICommandHolder fixture = new ICommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); fixture.TheCommand = ReactiveCommand.Create(() => executed = true, canExecute, ImmediateScheduler.Instance); source.OnNext(Unit.Default); @@ -528,7 +532,7 @@ public void InvokeCommandAgainstICommandInTargetSwallowsExceptions() command.ThrownExceptions.Subscribe(); fixture.TheCommand = command; Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); source.OnNext(Unit.Default); source.OnNext(Unit.Default); @@ -625,7 +629,7 @@ public void InvokeCommandAgainstReactiveCommandInTargetInvokesTheCommand() int executionCount = 0; ReactiveCommandHolder fixture = new ReactiveCommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); fixture.TheCommand = ReactiveCommand.Create(_ => { ++executionCount; }, outputScheduler: ImmediateScheduler.Instance); source.OnNext(0); @@ -641,7 +645,7 @@ public void InvokeCommandAgainstReactiveCommandInTargetPassesTheSpecifiedValueTo int executeReceived = 0; ReactiveCommandHolder fixture = new ReactiveCommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); fixture.TheCommand = ReactiveCommand.Create(x => executeReceived = x, outputScheduler: ImmediateScheduler.Instance); source.OnNext(42); @@ -655,7 +659,7 @@ public void InvokeCommandAgainstReactiveCommandInTargetRespectsCanExecute() BehaviorSubject canExecute = new BehaviorSubject(false); ReactiveCommandHolder fixture = new ReactiveCommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); fixture.TheCommand = ReactiveCommand.Create(_ => executed = true, canExecute, ImmediateScheduler.Instance); source.OnNext(0); @@ -673,7 +677,7 @@ public void InvokeCommandAgainstReactiveCommandInTargetRespectsCanExecuteWindow( BehaviorSubject canExecute = new BehaviorSubject(false); ReactiveCommandHolder fixture = new ReactiveCommandHolder(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); fixture.TheCommand = ReactiveCommand.Create(_ => executed = true, canExecute, ImmediateScheduler.Instance); source.OnNext(0); @@ -701,7 +705,7 @@ public void InvokeCommandAgainstReactiveCommandInTargetSwallowsExceptions() }; fixture.TheCommand.ThrownExceptions.Subscribe(); Subject source = new Subject(); - source.InvokeCommand(fixture, x => x.TheCommand); + source.InvokeCommand(fixture, x => x.TheCommand!); source.OnNext(0); source.OnNext(0); diff --git a/src/ReactiveUI.Tests/Comparers/OrderedComparerTests.cs b/src/ReactiveUI.Tests/Comparers/OrderedComparerTests.cs index e7608abcb3..d6fac5da45 100644 --- a/src/ReactiveUI.Tests/Comparers/OrderedComparerTests.cs +++ b/src/ReactiveUI.Tests/Comparers/OrderedComparerTests.cs @@ -89,7 +89,7 @@ public void WorksWithAnonymousTypes() [DebuggerDisplay("{Name}")] private class Employee { - public string Name { get; set; } + public string? Name { get; set; } public int Age { get; set; } diff --git a/src/ReactiveUI.Tests/InteractionsTest.cs b/src/ReactiveUI.Tests/InteractionsTest.cs index 90aa426aaf..fe47b50ef0 100644 --- a/src/ReactiveUI.Tests/InteractionsTest.cs +++ b/src/ReactiveUI.Tests/InteractionsTest.cs @@ -22,9 +22,9 @@ public void RegisterNullHandlerShouldCauseException() { var interaction = new Interaction(); - Assert.Throws(() => interaction.RegisterHandler((Action>)null)); - Assert.Throws(() => interaction.RegisterHandler(null)); - Assert.Throws(() => interaction.RegisterHandler((Func, IObservable>)null)); + Assert.Throws(() => interaction.RegisterHandler((Action>)null!)); + Assert.Throws(() => interaction.RegisterHandler(null!)); + Assert.Throws(() => interaction.RegisterHandler((Func, IObservable>)null!)); } [Fact] @@ -213,7 +213,7 @@ public void HandlersCanContainAsynchronousCodeViaTasks() return Task.FromResult(true); }); - string result = null; + string? result = null; interaction .Handle(Unit.Default) .Subscribe(r => result = r); diff --git a/src/ReactiveUI.Tests/Locator/Mocks/BarView.cs b/src/ReactiveUI.Tests/Locator/Mocks/BarView.cs index d548118004..40d4a24337 100644 --- a/src/ReactiveUI.Tests/Locator/Mocks/BarView.cs +++ b/src/ReactiveUI.Tests/Locator/Mocks/BarView.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -7,12 +7,12 @@ namespace ReactiveUI.Tests { public class BarView : IViewFor { - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (IBarViewModel)value; + set => ViewModel = (IBarViewModel?)value; } - public IBarViewModel ViewModel { get; set; } + public IBarViewModel? ViewModel { get; set; } } } diff --git a/src/ReactiveUI.Tests/Locator/Mocks/FooThatThrowsView.cs b/src/ReactiveUI.Tests/Locator/Mocks/FooThatThrowsView.cs index 81a075f4a0..8997591b11 100644 --- a/src/ReactiveUI.Tests/Locator/Mocks/FooThatThrowsView.cs +++ b/src/ReactiveUI.Tests/Locator/Mocks/FooThatThrowsView.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -14,12 +14,12 @@ public FooThatThrowsView() throw new InvalidOperationException("This is a test failure."); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (IFooViewModel)value; + set => ViewModel = (IFooViewModel?)value; } - public IFooViewModel ViewModel { get; set; } + public IFooViewModel? ViewModel { get; set; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Locator/Mocks/FooView.cs b/src/ReactiveUI.Tests/Locator/Mocks/FooView.cs index ca7c3b31d8..02e2b78636 100644 --- a/src/ReactiveUI.Tests/Locator/Mocks/FooView.cs +++ b/src/ReactiveUI.Tests/Locator/Mocks/FooView.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -7,12 +7,12 @@ namespace ReactiveUI.Tests { public class FooView : IFooView { - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (IFooViewModel)value; + set => ViewModel = (IFooViewModel?)value; } - public IFooViewModel ViewModel { get; set; } + public IFooViewModel? ViewModel { get; set; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Locator/Mocks/FooWithWeirdConvention.cs b/src/ReactiveUI.Tests/Locator/Mocks/FooWithWeirdConvention.cs index 669796a01d..88cc92fcd4 100644 --- a/src/ReactiveUI.Tests/Locator/Mocks/FooWithWeirdConvention.cs +++ b/src/ReactiveUI.Tests/Locator/Mocks/FooWithWeirdConvention.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -7,12 +7,12 @@ namespace ReactiveUI.Tests { public class FooWithWeirdConvention : IFooView { - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (IFooViewModel)value; + set => ViewModel = (IFooViewModel?)value; } - public IFooViewModel ViewModel { get; set; } + public IFooViewModel? ViewModel { get; set; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooCustomView.cs b/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooCustomView.cs index 8191172c32..b75228f4d4 100644 --- a/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooCustomView.cs +++ b/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooCustomView.cs @@ -7,12 +7,12 @@ namespace ReactiveUI.Tests { public class RoutableFooCustomView : IViewFor { - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (IRoutableFooViewModel)value; + set => ViewModel = (IRoutableFooViewModel?)value; } - public IRoutableFooViewModel ViewModel { get; set; } + public IRoutableFooViewModel? ViewModel { get; set; } } } diff --git a/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooView.cs b/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooView.cs index a65a85ed70..e041f06a22 100644 --- a/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooView.cs +++ b/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooView.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. +// Copyright (c) 2019 .NET Foundation and Contributors. All rights reserved. // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -7,12 +7,12 @@ namespace ReactiveUI.Tests { public class RoutableFooView : IViewFor { - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (IRoutableFooViewModel)value; + set => ViewModel = (IRoutableFooViewModel?)value; } - public IRoutableFooViewModel ViewModel { get; set; } + public IRoutableFooViewModel? ViewModel { get; set; } } } diff --git a/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooViewModel.cs b/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooViewModel.cs index 64e392bd71..10d02bf9bd 100644 --- a/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooViewModel.cs +++ b/src/ReactiveUI.Tests/Locator/Mocks/RoutableFooViewModel.cs @@ -7,8 +7,8 @@ namespace ReactiveUI.Tests { public class RoutableFooViewModel : ReactiveObject, IRoutableFooViewModel { - public IScreen HostScreen { get; set; } + public IScreen HostScreen { get; set; } = new TestScreen(); - public string UrlPathSegment { get; set; } + public string? UrlPathSegment { get; set; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/MessageBusTest.cs b/src/ReactiveUI.Tests/MessageBusTest.cs index 192b048c04..2fdc9eaffc 100644 --- a/src/ReactiveUI.Tests/MessageBusTest.cs +++ b/src/ReactiveUI.Tests/MessageBusTest.cs @@ -133,8 +133,8 @@ public void MessageBusThreadingTest() otherThread.Start(); otherThread.Join(); - Assert.NotEqual(listenedThreadId.Value, thisThreadId); - Assert.Equal(listenedThreadId.Value, otherThreadId.Value); + Assert.NotEqual(listenedThreadId!.Value, thisThreadId); + Assert.Equal(listenedThreadId.Value, otherThreadId!.Value); } } } diff --git a/src/ReactiveUI.Tests/Mocks/CommandBindViewModel.cs b/src/ReactiveUI.Tests/Mocks/CommandBindViewModel.cs index c214dc18c2..21e4b4d606 100644 --- a/src/ReactiveUI.Tests/Mocks/CommandBindViewModel.cs +++ b/src/ReactiveUI.Tests/Mocks/CommandBindViewModel.cs @@ -14,8 +14,8 @@ namespace ReactiveUI.Tests { public class CommandBindViewModel : ReactiveObject { - private ReactiveCommand _Command1; - private ReactiveCommand _Command2; + private ReactiveCommand _Command1 = null!; + private ReactiveCommand _Command2 = null!; private int _value; @@ -23,6 +23,7 @@ public CommandBindViewModel() { Command1 = ReactiveCommand.Create(_ => Unit.Default); Command2 = ReactiveCommand.Create(() => { }); + NestedViewModel = new FakeNestedViewModel(); } public ReactiveCommand Command1 diff --git a/src/ReactiveUI.Tests/Mocks/FakeCollectionViewModel.cs b/src/ReactiveUI.Tests/Mocks/FakeCollectionViewModel.cs index b6ed712a28..274db8d829 100644 --- a/src/ReactiveUI.Tests/Mocks/FakeCollectionViewModel.cs +++ b/src/ReactiveUI.Tests/Mocks/FakeCollectionViewModel.cs @@ -13,7 +13,7 @@ namespace ReactiveUI.Tests { public class FakeCollectionViewModel : ReactiveObject { - private readonly ObservableAsPropertyHelper _numberAsString; + private readonly ObservableAsPropertyHelper _numberAsString; public FakeCollectionViewModel(FakeCollectionModel model) { @@ -24,6 +24,6 @@ public FakeCollectionViewModel(FakeCollectionModel model) public FakeCollectionModel Model { get; protected set; } - public string NumberAsString => _numberAsString.Value; + public string? NumberAsString => _numberAsString.Value; } } diff --git a/src/ReactiveUI.Tests/Mocks/PropertyBindModel.cs b/src/ReactiveUI.Tests/Mocks/PropertyBindModel.cs index b017961ab9..26e87f3e54 100644 --- a/src/ReactiveUI.Tests/Mocks/PropertyBindModel.cs +++ b/src/ReactiveUI.Tests/Mocks/PropertyBindModel.cs @@ -15,6 +15,6 @@ public class PropertyBindModel { public int AThing { get; set; } - public string AnotherThing { get; set; } + public string? AnotherThing { get; set; } } } diff --git a/src/ReactiveUI.Tests/Mocks/PropertyBindViewModel.cs b/src/ReactiveUI.Tests/Mocks/PropertyBindViewModel.cs index 7614d6fa91..84392750b5 100644 --- a/src/ReactiveUI.Tests/Mocks/PropertyBindViewModel.cs +++ b/src/ReactiveUI.Tests/Mocks/PropertyBindViewModel.cs @@ -14,21 +14,21 @@ namespace ReactiveUI.Tests { public class PropertyBindViewModel : ReactiveObject { - private string _Property1; - private PropertyBindModel _Model; + private string? _Property1; + private PropertyBindModel? _Model; private int _Property2; private double _JustADouble; private decimal _JustADecimal; private double? _NullableDouble; private int _JustAInt32; - public PropertyBindViewModel(PropertyBindModel model = null) + public PropertyBindViewModel(PropertyBindModel? model = null) { Model = model ?? new PropertyBindModel { AThing = 42, AnotherThing = "Baz" }; SomeCollectionOfStrings = new ObservableCollectionExtended(new[] { "Foo", "Bar" }); } - public string Property1 + public string? Property1 { get => _Property1; set => this.RaiseAndSetIfChanged(ref _Property1, value); @@ -66,7 +66,7 @@ public double? NullableDouble public ObservableCollectionExtended SomeCollectionOfStrings { get; } - public PropertyBindModel Model + public PropertyBindModel? Model { get => _Model; set => this.RaiseAndSetIfChanged(ref _Model, value); diff --git a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs index 4fc82636f4..727ceb9f29 100644 --- a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs +++ b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs @@ -7,7 +7,7 @@ namespace ReactiveUI.Tests { internal class OAPHIndexerTestFixture : ReactiveObject { - private string _text; + private string? _text; public OAPHIndexerTestFixture() { @@ -16,12 +16,12 @@ public OAPHIndexerTestFixture() .Value; } - public string Text + public string? Text { get => _text; set => this.RaiseAndSetIfChanged(ref _text, value); } - public string this[string propertyName] => string.Empty; + public string? this[string propertyName] => string.Empty; } } diff --git a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs index d5074c94d7..4f12446e24 100644 --- a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs +++ b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs @@ -227,7 +227,7 @@ public void NoThrownExceptionsSubscriberEqualsOAPHDeath() } catch (Exception ex) { - failed = ex.InnerException.Message != "Die!"; + failed = ex?.InnerException?.Message != "Die!"; } Assert.False(failed); diff --git a/src/ReactiveUI.Tests/ObservedChanged/Mocks/NewGameViewModel.cs b/src/ReactiveUI.Tests/ObservedChanged/Mocks/NewGameViewModel.cs index dd27e790fb..5ea3576f21 100644 --- a/src/ReactiveUI.Tests/ObservedChanged/Mocks/NewGameViewModel.cs +++ b/src/ReactiveUI.Tests/ObservedChanged/Mocks/NewGameViewModel.cs @@ -13,7 +13,7 @@ namespace ReactiveUI.Tests { public class NewGameViewModel : ReactiveObject { - private string _newPlayerName; + private string? _newPlayerName; public NewGameViewModel() { @@ -38,10 +38,15 @@ public NewGameViewModel() var canAddPlayer = this.WhenAnyValue( x => x.Players.Count, x => x.NewPlayerName, - (count, newPlayerName) => count < 7 && !string.IsNullOrWhiteSpace(newPlayerName) && !Players.Contains(newPlayerName)); + (count, newPlayerName) => count < 7 && !string.IsNullOrWhiteSpace(newPlayerName) && !Players.Contains(newPlayerName!)); AddPlayer = ReactiveCommand.Create( () => { + if (NewPlayerName == null) + { + throw new InvalidOperationException("NewPlayerName is null"); + } + Players.Add(NewPlayerName.Trim()); NewPlayerName = string.Empty; }, @@ -58,10 +63,10 @@ public NewGameViewModel() public ReactiveCommand RandomizeOrder { get; } - public string NewPlayerName + public string? NewPlayerName { get => _newPlayerName; set => this.RaiseAndSetIfChanged(ref _newPlayerName, value); } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs b/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs index f730648955..3de9fee0bb 100644 --- a/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs +++ b/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs @@ -28,7 +28,7 @@ public void GetValueShouldActuallyReturnTheValue() // ...whereas ObservableForProperty *is* guaranteed to. fixture.ObservableForProperty(x => x.IsOnlyOneWord).Subscribe(x => { - output.Add(x.GetValue()); + output.Add(x.GetValue() !); }); foreach (var v in input) @@ -50,7 +50,7 @@ public void GetValueShouldReturnTheValueFromAPath() Child = new TestFixture { IsNotNullString = "Foo" }, }; - Expression> expression = x => x.Child.IsNotNullString; + Expression> expression = x => x!.Child!.IsNotNullString!; var fixture = new ObservedChange(input, expression.Body); Assert.Equal("Foo", fixture.GetValue()); @@ -64,10 +64,10 @@ public void SetValuePathSmokeTest() Child = new TestFixture { IsNotNullString = "Foo" }, }; - Expression> expression = x => x.IsOnlyOneWord; + Expression> expression = x => x.IsOnlyOneWord!; var fixture = new ObservedChange(new TestFixture { IsOnlyOneWord = "Bar" }, expression.Body); - fixture.SetValueToProperty(output, x => x.Child.IsNotNullString); + fixture.SetValueToProperty(output, x => x.Child!.IsNotNullString); Assert.Equal("Bar", output.Child.IsNotNullString); } @@ -79,7 +79,7 @@ public void BindToSmokeTest() var input = new ScheduledSubject(sched); var fixture = new HostTestFixture { Child = new TestFixture() }; - input.BindTo(fixture, x => x.Child.IsNotNullString); + input.BindTo(fixture, x => x.Child!.IsNotNullString); Assert.Null(fixture.Child.IsNotNullString); @@ -101,7 +101,7 @@ public void DisposingDisconnectsTheBindTo() var input = new ScheduledSubject(sched); var fixture = new HostTestFixture { Child = new TestFixture() }; - var subscription = input.BindTo(fixture, x => x.Child.IsNotNullString); + var subscription = input.BindTo(fixture, x => x.Child!.IsNotNullString); Assert.Null(fixture.Child.IsNotNullString); @@ -125,7 +125,7 @@ public void BindToIsNotFooledByIntermediateObjectSwitching() var input = new ScheduledSubject(sched); var fixture = new HostTestFixture { Child = new TestFixture() }; - input.BindTo(fixture, x => x.Child.IsNotNullString); + input.BindTo(fixture, x => x.Child!.IsNotNullString); Assert.Null(fixture.Child.IsNotNullString); diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CommandBindView.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CommandBindView.cs index cd92bdc9d1..cacc473a84 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CommandBindView.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CommandBindView.cs @@ -27,13 +27,13 @@ public CommandBindView() Command2 = new Image(); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (CommandBindViewModel)value; + set => ViewModel = (CommandBindViewModel?)value; } - public CommandBindViewModel ViewModel { get; set; } + public CommandBindViewModel? ViewModel { get; set; } public CustomClickButton Command1 { get; protected set; } diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CustomClickButton.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CustomClickButton.cs index 66f7e60c5c..a57987215c 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CustomClickButton.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/CustomClickButton.cs @@ -21,7 +21,7 @@ namespace ReactiveUI.Tests.Xaml { public class CustomClickButton : Button { - public event EventHandler CustomClick; + public event EventHandler? CustomClick; public void RaiseCustomClick() => CustomClick?.Invoke(this, EventArgs.Empty); diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/FakeView.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/FakeView.cs index dcd966d3ee..b6d7c850a7 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/FakeView.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/FakeView.cs @@ -28,12 +28,12 @@ public FakeView() public TextBox TheTextBox { get; protected set; } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (FakeViewModel)value; + set => ViewModel = (FakeViewModel?)value; } - public FakeViewModel ViewModel { get; set; } + public FakeViewModel? ViewModel { get; set; } } } diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/HostTestView.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/HostTestView.cs index 3796608f40..f16251ece2 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/HostTestView.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/HostTestView.cs @@ -17,16 +17,16 @@ public class HostTestView : Control, IViewFor { public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register("ViewModel", typeof(HostTestFixture), typeof(HostTestView), new PropertyMetadata(null)); - public HostTestFixture ViewModel + public HostTestFixture? ViewModel { get => (HostTestFixture)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (HostTestFixture)value; + set => ViewModel = (HostTestFixture?)value; } } } diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/PropertyBindView.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/PropertyBindView.cs index 2cd873564c..a682a49387 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/PropertyBindView.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/PropertyBindView.cs @@ -40,16 +40,16 @@ public PropertyBindView() public ListBox FakeItemsControl { get; set; } - public PropertyBindViewModel ViewModel + public PropertyBindViewModel? ViewModel { get => (PropertyBindViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (PropertyBindViewModel)value; + set => ViewModel = (PropertyBindViewModel?)value; } } } diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/ReactiveObjectCommandBindView.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/ReactiveObjectCommandBindView.cs index 1f7ebc6455..96a919d735 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/ReactiveObjectCommandBindView.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/Mocks/ReactiveObjectCommandBindView.cs @@ -21,7 +21,7 @@ namespace ReactiveUI.Tests.Xaml { public class ReactiveObjectCommandBindView : ReactiveObject, IViewFor { - private CommandBindViewModel _vm; + private CommandBindViewModel? _vm; public ReactiveObjectCommandBindView() { @@ -29,13 +29,13 @@ public ReactiveObjectCommandBindView() Command2 = new Image(); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (CommandBindViewModel)value; + set => ViewModel = (CommandBindViewModel?)value; } - public CommandBindViewModel ViewModel + public CommandBindViewModel? ViewModel { get => _vm; set => this.RaiseAndSetIfChanged(ref _vm, value); diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs index 6b2874916f..b28a8a737b 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/PropertyBindingTest.cs @@ -30,7 +30,7 @@ public void TwoWayBindWithFuncConvertersSmokeTest() vm.JustADecimal = 123.45m; Assert.NotEqual(vm.JustADecimal.ToString(), view.SomeTextBox.Text); - var disp = fixture.Bind(vm, view, x => x.JustADecimal, x => x.SomeTextBox.Text, (IObservable)null, d => d.ToString(), decimal.Parse); + var disp = fixture.Bind(vm, view, x => x.JustADecimal, x => x.SomeTextBox.Text, (IObservable?)null, d => d.ToString(), decimal.Parse); Assert.Equal(vm.JustADecimal.ToString(), view.SomeTextBox.Text); Assert.Equal(123.45m, vm.JustADecimal); @@ -38,7 +38,7 @@ public void TwoWayBindWithFuncConvertersSmokeTest() view.SomeTextBox.Text = "567.89"; Assert.Equal(567.89m, vm.JustADecimal); - disp.Dispose(); + disp?.Dispose(); vm.JustADecimal = 0; Assert.Equal(0, vm.JustADecimal); @@ -55,7 +55,7 @@ public void TwoWayBindSmokeTest() vm.Property1 = "Foo"; Assert.NotEqual(vm.Property1, view.SomeTextBox.Text); - var disp = fixture.Bind(vm, view, x => x.Property1, x => x.SomeTextBox.Text, (IObservable)null, null); + var disp = fixture.Bind(vm, view, x => x.Property1, x => x.SomeTextBox.Text, (IObservable?)null, null); Assert.Equal(vm.Property1, view.SomeTextBox.Text); Assert.Equal("Foo", vm.Property1); @@ -80,7 +80,7 @@ public void TypeConvertedTwoWayBindSmokeTest() vm.Property2 = 17; Assert.NotEqual(vm.Property2.ToString(), view.SomeTextBox.Text); - var disp = fixture.Bind(vm, view, x => x.Property2, x => x.SomeTextBox.Text, (IObservable)null, null); + var disp = fixture.Bind(vm, view, x => x.Property2, x => x.SomeTextBox.Text, (IObservable?)null, null); Assert.Equal(vm.Property2.ToString(), view.SomeTextBox.Text); Assert.Equal(17, vm.Property2); @@ -99,7 +99,7 @@ public void TypeConvertedTwoWayBindSmokeTest() Assert.NotEqual("0", view.SomeTextBox.Text); vm.JustADecimal = 17.2m; - var disp1 = fixture.Bind(vm, view, x => x.JustADecimal, x => x.SomeTextBox.Text, (IObservable)null, null); + var disp1 = fixture.Bind(vm, view, x => x.JustADecimal, x => x.SomeTextBox.Text, (IObservable?)null, null); Assert.Equal(vm.JustADecimal.ToString(), view.SomeTextBox.Text); Assert.Equal(17.2m, vm.JustADecimal); @@ -120,7 +120,7 @@ public void TypeConvertedTwoWayBindSmokeTest() // Empty test vm.JustAInt32 = 12; - var disp2 = fixture.Bind(vm, view, x => x.JustAInt32, x => x.SomeTextBox.Text, (IObservable)null, null); + var disp2 = fixture.Bind(vm, view, x => x.JustAInt32, x => x.SomeTextBox.Text, (IObservable?)null, null); view.SomeTextBox.Text = string.Empty; Assert.Equal(12, vm.JustAInt32); @@ -139,7 +139,7 @@ public void BindingIntoModelObjects() var vm = new PropertyBindViewModel(); var view = new PropertyBindView { ViewModel = vm }; - view.OneWayBind(view.ViewModel, x => x.Model.AnotherThing, x => x.SomeTextBox.Text); + view.OneWayBind(view.ViewModel, x => x!.Model!.AnotherThing, x => x.SomeTextBox.Text); Assert.Equal("Baz", view.SomeTextBox.Text); } @@ -240,11 +240,11 @@ public void BindToShouldntInitiallySetToNull() var vm = new PropertyBindViewModel(); var view = new PropertyBindView { ViewModel = null }; - view.OneWayBind(vm, x => x.Model.AnotherThing, x => x.FakeControl.NullHatingString); + view.OneWayBind(vm, x => x!.Model!.AnotherThing, x => x.FakeControl.NullHatingString); Assert.Equal(string.Empty, view.FakeControl.NullHatingString); view.ViewModel = vm; - Assert.Equal(vm.Model.AnotherThing, view.FakeControl.NullHatingString); + Assert.Equal(vm!.Model!.AnotherThing, view.FakeControl.NullHatingString); } [Fact] @@ -253,7 +253,7 @@ public void BindToTypeConversionSmokeTest() var vm = new PropertyBindViewModel(); var view = new PropertyBindView { ViewModel = null }; - view.WhenAnyValue(x => x.ViewModel.JustADouble) + view.WhenAnyValue(x => x.ViewModel!.JustADouble) .BindTo(view, x => x.FakeControl.NullHatingString); Assert.Equal(string.Empty, view.FakeControl.NullHatingString); @@ -268,8 +268,8 @@ public void BindToNullShouldThrowHelpfulError() var view = new PropertyBindView { ViewModel = null }; Assert.Throws(() => - view.WhenAnyValue(x => x.FakeControl.NullHatingString) - .BindTo(view.ViewModel, x => x.Property1)); + view.WhenAnyValue(x => x.FakeControl!.NullHatingString!) + .BindTo(view!.ViewModel!, x => x!.Property1)); } [Fact] @@ -351,10 +351,10 @@ public void BindExpectsConverterFuncsToNotBeNull() var view = new PropertyBindView { ViewModel = vm }; var fixture = new PropertyBinderImplementation(); - Func nullFunc = null; + Func nullFunc = null!; - Assert.Throws(() => fixture.Bind(vm, view, x => x.Property1, x => x.SomeTextBox.Text, (IObservable)null, nullFunc, s => s)); - Assert.Throws(() => fixture.Bind(vm, view, x => x.Property1, x => x.SomeTextBox.Text, (IObservable)null, s => s, nullFunc)); + Assert.Throws(() => fixture.Bind(vm, view, x => x.Property1, x => x.SomeTextBox.Text, (IObservable?)null, nullFunc, s => s)); + Assert.Throws(() => fixture.Bind(vm, view, x => x.Property1, x => x.SomeTextBox.Text, (IObservable?)null, s => s, nullFunc)); } [Fact] diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/Utilities/DispatcherUtilities.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/Utilities/DispatcherUtilities.cs index ca59ffaa93..8af95b6272 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/Utilities/DispatcherUtilities.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/Utilities/DispatcherUtilities.cs @@ -28,7 +28,7 @@ public static void DoEvents() } [SuppressMessage("Design", "CA1801: Parameter never used", Justification = "Used on some platforms.")] - public static object ExitFrame(object f) + public static object? ExitFrame(object f) { #if !NETFX_CORE ((DispatcherFrame)f).Continue = false; diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/WhenAnyThroughDependencyObjectTests.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/WhenAnyThroughDependencyObjectTests.cs index 869f781d33..bd5782d652 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/WhenAnyThroughDependencyObjectTests.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/WhenAnyThroughDependencyObjectTests.cs @@ -36,7 +36,7 @@ public void WhenAnyThroughAViewShouldntGiveNullValues() Assert.Equal(0, output.Count); Assert.Null(fixture.ViewModel); - fixture.WhenAnyValue(x => x.ViewModel.Child.IsNotNullString).Subscribe(output.Add); + fixture.WhenAnyValue(x => x.ViewModel!.Child!.IsNotNullString!).Subscribe(output.Add); fixture.ViewModel = vm; Assert.Equal(1, output.Count); diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs index c3845ea9a3..29fd8030ad 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs @@ -36,7 +36,7 @@ public class XamlViewCommandTests public void EventBinderBindsToExplicitInheritedEvent() { var fixture = new FakeView(); - fixture.BindCommand(fixture.ViewModel, x => x.Cmd, x => x.TheTextBox, "MouseDown"); + fixture.BindCommand(fixture!.ViewModel!, x => x!.Cmd, x => x.TheTextBox, "MouseDown"); } [Fact] @@ -62,7 +62,7 @@ public void EventBinderBindsToImplicitEvent() DispatcherUtilities.DoEvents(); Assert.Equal(1, invokeCount); - disp.Dispose(); + disp?.Dispose(); invoker.Invoke(); Assert.Equal(1, invokeCount); } diff --git a/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.net472.approved.txt b/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.net472.approved.txt index c4a856de0f..b1babfa47d 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.net472.approved.txt +++ b/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.net472.approved.txt @@ -15,20 +15,20 @@ namespace ReactiveUI.Winforms public class CreatesWinformsCommandBinding : ReactiveUI.ICreatesCommandBinding { public CreatesWinformsCommandBinding() { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class PanelSetMethodBindingConverter : ReactiveUI.ISetMethodBindingConverter, Splat.IEnableLogger { public PanelSetMethodBindingConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public object PerformSet(object toTarget, object newValue, object[] arguments) { } + public object PerformSet(object? toTarget, object? newValue, object[]? arguments) { } } public class PlatformOperations { public PlatformOperations() { } - public string GetOrientation() { } + public string? GetOrientation() { } } public class ReactiveUserControl : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class @@ -52,23 +52,23 @@ namespace ReactiveUI.Winforms public RoutedControlHost() { } [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The default control when no viewmodel is specified")] - public System.Windows.Forms.Control DefaultContent { get; set; } + public System.Windows.Forms.Control? DefaultContent { get; set; } [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The router.")] - public ReactiveUI.RoutingState Router { get; set; } + public ReactiveUI.RoutingState? Router { get; set; } [System.ComponentModel.Browsable(false)] - public System.IObservable ViewContractObservable { get; set; } + public System.IObservable? ViewContractObservable { get; set; } [System.ComponentModel.Browsable(false)] - public ReactiveUI.IViewLocator ViewLocator { get; set; } - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging; + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged; + public event System.ComponentModel.PropertyChangingEventHandler? PropertyChanging; protected override void Dispose(bool disposing) { } } public class TableContentSetMethodBindingConverter : ReactiveUI.ISetMethodBindingConverter, Splat.IEnableLogger { public TableContentSetMethodBindingConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public object PerformSet(object toTarget, object newValue, object[] arguments) { } + public object PerformSet(object? toTarget, object? newValue, object[]? arguments) { } } [System.ComponentModel.DefaultProperty("ViewModel")] public class ViewModelControlHost : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IReactiveObject, ReactiveUI.IViewFor, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging @@ -82,22 +82,22 @@ namespace ReactiveUI.Winforms [System.ComponentModel.Bindable(true)] [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The Current View")] - public object Content { get; set; } - public System.Windows.Forms.Control CurrentView { get; } + public object? Content { get; set; } + public System.Windows.Forms.Control? CurrentView { get; } [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The default control when no viewmodel is specified")] - public System.Windows.Forms.Control DefaultContent { get; set; } + public System.Windows.Forms.Control? DefaultContent { get; set; } [System.ComponentModel.Browsable(false)] - public System.IObservable ViewContractObservable { get; set; } + public System.IObservable? ViewContractObservable { get; set; } [System.ComponentModel.Browsable(false)] - public ReactiveUI.IViewLocator ViewLocator { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } [System.ComponentModel.Bindable(true)] [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The viewmodel to host.")] - public object ViewModel { get; set; } + public object? ViewModel { get; set; } public static bool DefaultCacheViewsEnabled { get; set; } - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging; + public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged; + public event System.ComponentModel.PropertyChangingEventHandler? PropertyChanging; protected override void Dispose(bool disposing) { } } public class WinformsCreatesObservableForProperty : ReactiveUI.ICreatesObservableForProperty, Splat.IEnableLogger diff --git a/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.netcoreapp3.1.approved.txt b/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.netcoreapp3.1.approved.txt index 0dc676fcf4..9cbbe61b09 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.netcoreapp3.1.approved.txt +++ b/src/ReactiveUI.Tests/Platforms/winforms/API/ApiApprovalTests.Winforms.netcoreapp3.1.approved.txt @@ -15,20 +15,20 @@ namespace ReactiveUI.Winforms public class CreatesWinformsCommandBinding : ReactiveUI.ICreatesCommandBinding { public CreatesWinformsCommandBinding() { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } - public System.IDisposable BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter) { } + public System.IDisposable? BindCommandToObject(System.Windows.Input.ICommand command, object target, System.IObservable commandParameter, string eventName) { } public int GetAffinityForObject(System.Type type, bool hasEventTarget) { } } public class PanelSetMethodBindingConverter : ReactiveUI.ISetMethodBindingConverter, Splat.IEnableLogger { public PanelSetMethodBindingConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public object PerformSet(object toTarget, object newValue, object[] arguments) { } + public object PerformSet(object? toTarget, object? newValue, object[]? arguments) { } } public class PlatformOperations { public PlatformOperations() { } - public string GetOrientation() { } + public string? GetOrientation() { } } public class ReactiveUserControl : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class @@ -52,23 +52,23 @@ namespace ReactiveUI.Winforms public RoutedControlHost() { } [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The default control when no viewmodel is specified")] - public System.Windows.Forms.Control DefaultContent { get; set; } + public System.Windows.Forms.Control? DefaultContent { get; set; } [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The router.")] - public ReactiveUI.RoutingState Router { get; set; } + public ReactiveUI.RoutingState? Router { get; set; } [System.ComponentModel.Browsable(false)] - public System.IObservable ViewContractObservable { get; set; } + public System.IObservable? ViewContractObservable { get; set; } [System.ComponentModel.Browsable(false)] - public ReactiveUI.IViewLocator ViewLocator { get; set; } - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging; + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged; + public event System.ComponentModel.PropertyChangingEventHandler? PropertyChanging; protected override void Dispose(bool disposing) { } } public class TableContentSetMethodBindingConverter : ReactiveUI.ISetMethodBindingConverter, Splat.IEnableLogger { public TableContentSetMethodBindingConverter() { } public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } - public object PerformSet(object toTarget, object newValue, object[] arguments) { } + public object PerformSet(object? toTarget, object? newValue, object[]? arguments) { } } [System.ComponentModel.DefaultProperty("ViewModel")] public class ViewModelControlHost : System.Windows.Forms.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IReactiveObject, ReactiveUI.IViewFor, Splat.IEnableLogger, System.ComponentModel.INotifyPropertyChanged, System.ComponentModel.INotifyPropertyChanging @@ -82,22 +82,22 @@ namespace ReactiveUI.Winforms [System.ComponentModel.Bindable(true)] [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The Current View")] - public object Content { get; set; } - public System.Windows.Forms.Control CurrentView { get; } + public object? Content { get; set; } + public System.Windows.Forms.Control? CurrentView { get; } [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The default control when no viewmodel is specified")] - public System.Windows.Forms.Control DefaultContent { get; set; } + public System.Windows.Forms.Control? DefaultContent { get; set; } [System.ComponentModel.Browsable(false)] - public System.IObservable ViewContractObservable { get; set; } + public System.IObservable? ViewContractObservable { get; set; } [System.ComponentModel.Browsable(false)] - public ReactiveUI.IViewLocator ViewLocator { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } [System.ComponentModel.Bindable(true)] [System.ComponentModel.Category("ReactiveUI")] [System.ComponentModel.Description("The viewmodel to host.")] - public object ViewModel { get; set; } + public object? ViewModel { get; set; } public static bool DefaultCacheViewsEnabled { get; set; } - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging; + public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged; + public event System.ComponentModel.PropertyChangingEventHandler? PropertyChanging; protected override void Dispose(bool disposing) { } } public class WinformsCreatesObservableForProperty : ReactiveUI.ICreatesObservableForProperty, Splat.IEnableLogger diff --git a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs index 36cb779cca..353e760dae 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs @@ -24,7 +24,7 @@ public void CommandBinderBindsToButton() Assert.True(fixture.GetAffinityForObject(input.GetType(), true) > 0); Assert.True(fixture.GetAffinityForObject(input.GetType(), false) > 0); var commandExecuted = false; - object ea = null; + object? ea = null; cmd.Subscribe(o => { ea = o; @@ -50,7 +50,7 @@ public void CommandBinderBindsToCustomControl() Assert.True(fixture.GetAffinityForObject(input.GetType(), true) > 0); Assert.True(fixture.GetAffinityForObject(input.GetType(), false) > 0); var commandExecuted = false; - object ea = null; + object? ea = null; cmd.Subscribe(o => { ea = o; @@ -76,7 +76,7 @@ public void CommandBinderBindsToCustomComponent() Assert.True(fixture.GetAffinityForObject(input.GetType(), true) > 0); Assert.True(fixture.GetAffinityForObject(input.GetType(), false) > 0); var commandExecuted = false; - object ea = null; + object? ea = null; cmd.Subscribe(o => { ea = o; diff --git a/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs index 8974eb0808..36e210f6f3 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs @@ -75,7 +75,7 @@ public void WinformsCreatesObservableForPropertyWorksForThirdPartyControls() Assert.NotEqual(0, fixture.GetAffinityForObject(typeof(AThirdPartyNamespace.ThirdPartyControl), "Value")); - Expression> expression = x => x.Value; + Expression> expression = x => x.Value; var propertyName = expression.Body.GetMemberInfo().Name; var dispose = fixture.GetNotificationForProperty(input, expression.Body, propertyName).ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var output).Subscribe(); Assert.Equal(0, output.Count); diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/CustomClickableComponent.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/CustomClickableComponent.cs index 93915df400..635f3cc4be 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/CustomClickableComponent.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/CustomClickableComponent.cs @@ -10,11 +10,11 @@ namespace ReactiveUI.Tests.Winforms { public class CustomClickableComponent : Component { - public event EventHandler Click; + public event EventHandler? Click; public void PerformClick() { Click?.Invoke(this, EventArgs.Empty); } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeView.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeView.cs index 5446582f12..1f7cb8776b 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeView.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeView.cs @@ -17,12 +17,12 @@ public FakeView() public TextBox TheTextBox { get; protected set; } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (FakeViewModel)value; + set => ViewModel = (FakeViewModel?)value; } - public FakeViewModel ViewModel { get; set; } + public FakeViewModel? ViewModel { get; set; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeViewLocator.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeViewLocator.cs index db35765c33..f354feadf8 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeViewLocator.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeViewLocator.cs @@ -9,12 +9,16 @@ namespace ReactiveUI.Tests.Winforms { internal class FakeViewLocator : IViewLocator { - public Func LocatorFunc { get; set; } + public Func? LocatorFunc { get; set; } - public IViewFor ResolveView(T viewModel, string contract = null) - where T : class + public IViewFor? ResolveView(T viewModel, string? contract = null) { - return LocatorFunc(viewModel.GetType()); + if (viewModel is null) + { + throw new ArgumentNullException(nameof(viewModel)); + } + + return LocatorFunc?.Invoke(viewModel.GetType()); } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformViewModel.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformViewModel.cs index f801aff6f0..b0a93b5c71 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformViewModel.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformViewModel.cs @@ -9,16 +9,16 @@ public class FakeWinformViewModel : ReactiveObject, IRoutableViewModel { private bool _someBooleanProperty; private int _someInteger; - private string _someText; + private string? _someText; private double _someDouble; - private string _property1; - private string _property2; - private string _property3; - private string _property4; + private string? _property1; + private string? _property2; + private string? _property3; + private string? _property4; - public FakeWinformViewModel(IScreen screen = null) + public FakeWinformViewModel(IScreen? screen = null) { - HostScreen = screen; + HostScreen = screen ?? new TestScreen(); } public string UrlPathSegment => "fake"; @@ -31,7 +31,7 @@ public int SomeInteger set => this.RaiseAndSetIfChanged(ref _someInteger, value); } - public string SomeText + public string? SomeText { get => _someText; set => this.RaiseAndSetIfChanged(ref _someText, value); @@ -43,25 +43,25 @@ public double SomeDouble set => this.RaiseAndSetIfChanged(ref _someDouble, value); } - public string Property1 + public string? Property1 { get => _property1; set => this.RaiseAndSetIfChanged(ref _property1, value); } - public string Property2 + public string? Property2 { get => _property2; set => this.RaiseAndSetIfChanged(ref _property2, value); } - public string Property3 + public string? Property3 { get => _property3; set => this.RaiseAndSetIfChanged(ref _property3, value); } - public string Property4 + public string? Property4 { get => _property4; set => this.RaiseAndSetIfChanged(ref _property4, value); @@ -73,4 +73,4 @@ public bool BooleanProperty set => this.RaiseAndSetIfChanged(ref _someBooleanProperty, value); } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformsView.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformsView.cs index 71f8dfa882..53cbf34e2c 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformsView.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/FakeWinformsView.cs @@ -19,13 +19,13 @@ public FakeWinformsView() SomeDouble = new TextBox(); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (FakeWinformViewModel)value; + set => ViewModel = (FakeWinformViewModel?)value; } - public FakeWinformViewModel ViewModel { get; set; } + public FakeWinformViewModel? ViewModel { get; set; } public Button Property1 { get; } @@ -39,4 +39,4 @@ object IViewFor.ViewModel public TextBox SomeDouble { get; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/ThirdPartyControl.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/ThirdPartyControl.cs index d5a83a1036..8c3f5c1a51 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/ThirdPartyControl.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/ThirdPartyControl.cs @@ -10,11 +10,11 @@ namespace AThirdPartyNamespace { public class ThirdPartyControl : Control { - private string _value; + private string? _value; - public event EventHandler ValueChanged; + public event EventHandler? ValueChanged; - public string Value + public string? Value { get => _value; set diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindView.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindView.cs index 468e4e16f6..a9daeb333e 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindView.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindView.cs @@ -15,13 +15,13 @@ public WinformCommandBindView() Command2 = new CustomClickableControl(); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (WinformCommandBindViewModel)value; + set => ViewModel = (WinformCommandBindViewModel?)value; } - public WinformCommandBindViewModel ViewModel { get; set; } + public WinformCommandBindViewModel? ViewModel { get; set; } public Button Command1 { get; protected set; } diff --git a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindViewModel.cs b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindViewModel.cs index 436ab514e3..68ac1a3961 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindViewModel.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/Mocks/WinformCommandBindViewModel.cs @@ -16,8 +16,8 @@ public class WinformCommandBindViewModel : ReactiveObject public WinformCommandBindViewModel() { - Command1 = ReactiveCommand.Create(() => { }, outputScheduler: ImmediateScheduler.Instance); - Command2 = ReactiveCommand.Create(() => { }, outputScheduler: ImmediateScheduler.Instance); + _command1 = ReactiveCommand.Create(() => { }, outputScheduler: ImmediateScheduler.Instance); + _command2 = ReactiveCommand.Create(() => { }, outputScheduler: ImmediateScheduler.Instance); } public ReactiveCommand Command1 diff --git a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs index ca599905fe..8124800120 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs @@ -21,14 +21,14 @@ public void ShouldDisposePreviousView() var viewLocator = new FakeViewLocator { LocatorFunc = t => new FakeWinformsView() }; var router = new RoutingState(); var target = new WinFormsRoutedViewHost { Router = router, ViewLocator = viewLocator }; - router.Navigate.Execute(new FakeWinformViewModel()); + router?.Navigate?.Execute(new FakeWinformViewModel()); var currentView = target.Controls.OfType().Single(); var isDisposed = false; currentView.Disposed += (o, e) => isDisposed = true; // switch the viewmodel - router.Navigate.Execute(new FakeWinformViewModel()); + router?.Navigate?.Execute(new FakeWinformViewModel()); Assert.True(isDisposed); } @@ -55,7 +55,7 @@ public void WhenRoutedToViewModelItShouldAddViewToControls() var viewLocator = new FakeViewLocator { LocatorFunc = t => new FakeWinformsView() }; var router = new RoutingState(); var target = new WinFormsRoutedViewHost { Router = router, ViewLocator = viewLocator }; - router.Navigate.Execute(new FakeWinformViewModel()); + router?.Navigate?.Execute(new FakeWinformViewModel()); Assert.Equal(1, target.Controls.OfType().Count()); } diff --git a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs index 947fb828de..d5531c0546 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs @@ -46,7 +46,7 @@ public void ShouldDisposePreviousView() var currentView = target.CurrentView; var isDisposed = false; - currentView.Disposed += (o, e) => isDisposed = true; + currentView!.Disposed += (o, e) => isDisposed = true; // switch the viewmodel target.ViewModel = new FakeWinformViewModel(); diff --git a/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.net461.approved.txt b/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.net461.approved.txt index d0a4a42c6a..14a44c4879 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.net461.approved.txt +++ b/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.net461.approved.txt @@ -50,7 +50,7 @@ namespace ReactiveUI public static readonly System.Windows.DependencyProperty ViewModelProperty; public ReactivePage() { } public TViewModel BindingRoot { get; } - public TViewModel ViewModel { get; set; } + public TViewModel? ViewModel { get; set; } } public class ReactiveUserControl : System.Windows.Controls.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class @@ -58,7 +58,7 @@ namespace ReactiveUI public static readonly System.Windows.DependencyProperty ViewModelProperty; public ReactiveUserControl() { } public TViewModel BindingRoot { get; } - public TViewModel ViewModel { get; set; } + public TViewModel? ViewModel { get; set; } } public class ReactiveWindow : System.Windows.Window, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class @@ -66,7 +66,7 @@ namespace ReactiveUI public static readonly System.Windows.DependencyProperty ViewModelProperty; public ReactiveWindow() { } public TViewModel BindingRoot { get; } - public TViewModel ViewModel { get; set; } + public TViewModel? ViewModel { get; set; } } public class RoutedViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, Splat.IEnableLogger { @@ -129,4 +129,4 @@ namespace ReactiveUI.Wpf public Registrations() { } public void Register(System.Action, System.Type> registerFunction) { } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.netcoreapp3.0.approved.txt b/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.netcoreapp3.0.approved.txt index 2c051ccd58..0bdb2d87df 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.netcoreapp3.0.approved.txt +++ b/src/ReactiveUI.Tests/Platforms/wpf/API/ApiApprovalTests.Wpf.netcoreapp3.0.approved.txt @@ -50,7 +50,7 @@ namespace ReactiveUI public static readonly System.Windows.DependencyProperty ViewModelProperty; public ReactivePage() { } public TViewModel BindingRoot { get; } - public TViewModel ViewModel { get; set; } + public TViewModel? ViewModel { get; set; } } public class ReactiveUserControl : System.Windows.Controls.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class @@ -58,7 +58,7 @@ namespace ReactiveUI public static readonly System.Windows.DependencyProperty ViewModelProperty; public ReactiveUserControl() { } public TViewModel BindingRoot { get; } - public TViewModel ViewModel { get; set; } + public TViewModel? ViewModel { get; set; } } public class ReactiveWindow : System.Windows.Window, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor where TViewModel : class @@ -66,7 +66,7 @@ namespace ReactiveUI public static readonly System.Windows.DependencyProperty ViewModelProperty; public ReactiveWindow() { } public TViewModel BindingRoot { get; } - public TViewModel ViewModel { get; set; } + public TViewModel? ViewModel { get; set; } } public class RoutedViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, Splat.IEnableLogger { @@ -129,4 +129,4 @@ namespace ReactiveUI.Wpf public Registrations() { } public void Register(System.Action, System.Type> registerFunction) { } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingView.cs b/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingView.cs index 94ae129ccf..5b0494c620 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingView.cs +++ b/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingView.cs @@ -21,13 +21,13 @@ public CommandBindingView() Command2 = new Image(); } - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (CommandBindingViewModel)value; + set => ViewModel = (CommandBindingViewModel?)value; } - public CommandBindingViewModel ViewModel { get; set; } + public CommandBindingViewModel? ViewModel { get; set; } public CustomClickButton Command1 { get; protected set; } diff --git a/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingViewModel.cs b/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingViewModel.cs index 7e6f08afcb..fe45477f7e 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingViewModel.cs +++ b/src/ReactiveUI.Tests/Platforms/wpf/Mocks/CommandBindingViewModel.cs @@ -22,8 +22,8 @@ public class CommandBindingViewModel : ReactiveObject public CommandBindingViewModel() { - Command1 = ReactiveCommand.Create(_ => Unit.Default, outputScheduler: ImmediateScheduler.Instance); - Command2 = ReactiveCommand.Create(() => { }, outputScheduler: ImmediateScheduler.Instance); + _Command1 = ReactiveCommand.Create(_ => Unit.Default, outputScheduler: ImmediateScheduler.Instance); + _Command2 = ReactiveCommand.Create(() => { }, outputScheduler: ImmediateScheduler.Instance); } public ReactiveCommand Command1 @@ -38,7 +38,7 @@ public ReactiveCommand Command2 set => this.RaiseAndSetIfChanged(ref _Command2, value); } - public FakeNestedViewModel NestedViewModel { get; set; } + public FakeNestedViewModel? NestedViewModel { get; set; } public int Value { diff --git a/src/ReactiveUI.Tests/Platforms/wpf/Mocks/FakeXamlCommandBindingView.cs b/src/ReactiveUI.Tests/Platforms/wpf/Mocks/FakeXamlCommandBindingView.cs index 32efd7bb80..9963e46eba 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/Mocks/FakeXamlCommandBindingView.cs +++ b/src/ReactiveUI.Tests/Platforms/wpf/Mocks/FakeXamlCommandBindingView.cs @@ -13,17 +13,17 @@ public FakeXamlCommandBindingView() { _buttonDeclaredInXaml = new Button(); - this.BindCommand(ViewModel, vm => vm.Command2, v => v._buttonDeclaredInXaml); + this.BindCommand(ViewModel!, vm => vm!.Command2!, v => v._buttonDeclaredInXaml); } public string NameOfButtonDeclaredInXaml => nameof(_buttonDeclaredInXaml); - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (CommandBindingViewModel)value; + set => ViewModel = (CommandBindingViewModel?)value; } - public CommandBindingViewModel ViewModel { get; set; } + public CommandBindingViewModel? ViewModel { get; set; } } } diff --git a/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphNameOfTestFixture.cs b/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphNameOfTestFixture.cs index ec24eb50ec..1f4239622f 100644 --- a/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphNameOfTestFixture.cs +++ b/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphNameOfTestFixture.cs @@ -11,10 +11,10 @@ namespace ReactiveUI.Tests public class OaphNameOfTestFixture : TestFixture { [IgnoreDataMember] - private readonly ObservableAsPropertyHelper _firstThreeLettersOfOneWord; + private readonly ObservableAsPropertyHelper _firstThreeLettersOfOneWord; [IgnoreDataMember] - private readonly ObservableAsPropertyHelper _lastThreeLettersOfOneWord; + private readonly ObservableAsPropertyHelper _lastThreeLettersOfOneWord; public OaphNameOfTestFixture() { @@ -24,9 +24,9 @@ public OaphNameOfTestFixture() } [IgnoreDataMember] - public string FirstThreeLettersOfOneWord => _firstThreeLettersOfOneWord.Value; + public string? FirstThreeLettersOfOneWord => _firstThreeLettersOfOneWord.Value; [IgnoreDataMember] - public string LastThreeLettersOfOneWord => _lastThreeLettersOfOneWord.Value; + public string? LastThreeLettersOfOneWord => _lastThreeLettersOfOneWord.Value; } } diff --git a/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphTestFixture.cs b/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphTestFixture.cs index e178601154..bb60088031 100644 --- a/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphTestFixture.cs +++ b/src/ReactiveUI.Tests/ReactiveObject/Mocks/OaphTestFixture.cs @@ -11,7 +11,7 @@ namespace ReactiveUI.Tests public class OaphTestFixture : TestFixture { [IgnoreDataMember] - private readonly ObservableAsPropertyHelper _firstThreeLettersOfOneWord; + private readonly ObservableAsPropertyHelper _firstThreeLettersOfOneWord; public OaphTestFixture() { @@ -19,6 +19,6 @@ public OaphTestFixture() } [IgnoreDataMember] - public string FirstThreeLettersOfOneWord => _firstThreeLettersOfOneWord.Value; + public string? FirstThreeLettersOfOneWord => _firstThreeLettersOfOneWord.Value; } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/ReactiveObject/Mocks/TestFixture.cs b/src/ReactiveUI.Tests/ReactiveObject/Mocks/TestFixture.cs index 72fe8c15e1..d44cce4885 100644 --- a/src/ReactiveUI.Tests/ReactiveObject/Mocks/TestFixture.cs +++ b/src/ReactiveUI.Tests/ReactiveObject/Mocks/TestFixture.cs @@ -14,24 +14,24 @@ namespace ReactiveUI.Tests public class TestFixture : ReactiveObject { [IgnoreDataMember] - private string _isNotNullString; + private string? _isNotNullString; [IgnoreDataMember] - private string _isOnlyOneWord; + private string? _isOnlyOneWord; - private string _notSerialized; + private string? _notSerialized; [IgnoreDataMember] private int? _nullableInt; [IgnoreDataMember] - private string _pocoProperty; + private string? _pocoProperty; [IgnoreDataMember] - private List _stackOverflowTrigger; + private List? _stackOverflowTrigger; [IgnoreDataMember] - private string _usesExprRaiseSet; + private string? _usesExprRaiseSet; public TestFixture() { @@ -39,20 +39,20 @@ public TestFixture() } [DataMember] - public string IsNotNullString + public string? IsNotNullString { get => _isNotNullString; set => this.RaiseAndSetIfChanged(ref _isNotNullString, value); } [DataMember] - public string IsOnlyOneWord + public string? IsOnlyOneWord { get => _isOnlyOneWord; set => this.RaiseAndSetIfChanged(ref _isOnlyOneWord, value); } - public string NotSerialized + public string? NotSerialized { get => _notSerialized; set => this.RaiseAndSetIfChanged(ref _notSerialized, value); @@ -66,14 +66,14 @@ public int? NullableInt } [DataMember] - public string PocoProperty + public string? PocoProperty { get => _pocoProperty; set => _pocoProperty = value; } [DataMember] - public List StackOverflowTrigger + public List? StackOverflowTrigger { get => _stackOverflowTrigger; set => this.RaiseAndSetIfChanged(ref _stackOverflowTrigger, value.ToList()); @@ -83,7 +83,7 @@ public List StackOverflowTrigger public ObservableCollectionExtended TestCollection { get; protected set; } [DataMember] - public string UsesExprRaiseSet + public string? UsesExprRaiseSet { get => _usesExprRaiseSet; set => this.RaiseAndSetIfChanged(ref _usesExprRaiseSet, value); diff --git a/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs b/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs index 9c9effb030..e8406c62ab 100644 --- a/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs +++ b/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs @@ -132,8 +132,8 @@ public void ObservableForPropertyUsingExpression() IsNotNullString = "Foo", IsOnlyOneWord = "Baz" }; - var output = new List>(); - fixture.ObservableForProperty(x => x.IsNotNullString).Subscribe(x => { output.Add(x); }); + var output = new List>(); + fixture.ObservableForProperty(x => x.IsNotNullString).Subscribe(x => { output.Add(x!); }); fixture.IsNotNullString = "Bar"; fixture.IsNotNullString = "Baz"; @@ -179,7 +179,7 @@ public void ReactiveObjectShouldntSerializeAnythingExtra() IsNotNullString = "Foo", IsOnlyOneWord = "Baz" }; - string json = JSONHelper.Serialize(fixture); + string? json = JSONHelper.Serialize(fixture); // Should look something like: // {"IsNotNullString":"Foo","IsOnlyOneWord":"Baz","NullableInt":null,"PocoProperty":null,"StackOverflowTrigger":null,"TestCollection":[],"UsesExprRaiseSet":null} diff --git a/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj b/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj index ee7b20e899..a0f6f5ace9 100644 --- a/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj +++ b/src/ReactiveUI.Tests/ReactiveUI.Tests.csproj @@ -3,6 +3,7 @@ netstandard2.0;netcoreapp3.1 $(TargetFrameworks);net472 + enable latest diff --git a/src/ReactiveUI.Tests/Resolvers/DependencyResolverTests.cs b/src/ReactiveUI.Tests/Resolvers/DependencyResolverTests.cs index f58881037d..c7a68f10cb 100644 --- a/src/ReactiveUI.Tests/Resolvers/DependencyResolverTests.cs +++ b/src/ReactiveUI.Tests/Resolvers/DependencyResolverTests.cs @@ -52,7 +52,7 @@ private static Dictionary> GetServicesThatShouldBeRegistered() new Registrations().Register((factory, serviceType) => { - if (serviceTypeToImplementationTypes.TryGetValue(serviceType, out List implementationTypes) == false) + if (serviceTypeToImplementationTypes.TryGetValue(serviceType, out var implementationTypes) == false) { implementationTypes = new List(); serviceTypeToImplementationTypes.Add(serviceType, implementationTypes); @@ -63,7 +63,7 @@ private static Dictionary> GetServicesThatShouldBeRegistered() new PlatformRegistrations().Register((factory, serviceType) => { - if (serviceTypeToImplementationTypes.TryGetValue(serviceType, out List implementationTypes) == false) + if (serviceTypeToImplementationTypes.TryGetValue(serviceType, out var implementationTypes) == false) { implementationTypes = new List(); serviceTypeToImplementationTypes.Add(serviceType, implementationTypes); @@ -86,14 +86,14 @@ private static Dictionary> GetServicesThatShouldBeRegistered() private static void GetRegistrationsForPlatform(string typeName, Dictionary> serviceTypeToImplementationTypes) { - Type platformRegistrationsType = Type.GetType(typeName); + var platformRegistrationsType = Type.GetType(typeName); if (platformRegistrationsType != null) { var platformRegistrations = Activator.CreateInstance(platformRegistrationsType); - System.Reflection.MethodInfo register = platformRegistrationsType.GetMethod("Register"); + var register = platformRegistrationsType.GetMethod("Register"); var registerParameter = new Action, Type>((factory, serviceType) => { - if (serviceTypeToImplementationTypes.TryGetValue(serviceType, out List implementationTypes) == false) + if (serviceTypeToImplementationTypes.TryGetValue(serviceType, out var implementationTypes) == false) { implementationTypes = new List(); serviceTypeToImplementationTypes.Add(serviceType, implementationTypes); @@ -102,7 +102,7 @@ private static void GetRegistrationsForPlatform(string typeName, Dictionary> expr = x => x.Property1; + Expression> expr = x => x!.Property1; var exp = Reflection.Rewrite(expr.Body); var changes = new List>(); @@ -58,7 +58,7 @@ public void NotificationOnPropertyChanging() var testClass = new TestClassChanging(); - Expression> expr = x => x.Property1; + Expression> expr = x => x.Property1; var exp = Reflection.Rewrite(expr.Body); var changes = new List>(); @@ -80,7 +80,7 @@ public void NotificationOnWholeObjectChanged() var testClass = new TestClassChanged(); - Expression> expr = x => x.Property1; + Expression> expr = x => x.Property1; var exp = Reflection.Rewrite(expr.Body); var changes = new List>(); @@ -102,7 +102,7 @@ public void NotificationOnWholeObjectChanging() var testClass = new TestClassChanging(); - Expression> expr = x => x.Property1; + Expression> expr = x => x.Property1; var exp = Reflection.Rewrite(expr.Body); var changes = new List>(); @@ -119,13 +119,13 @@ public void NotificationOnWholeObjectChanging() private class TestClassChanged : INotifyPropertyChanged { - private string _property; + private string? _property; - private string _property2; + private string? _property2; - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; - public string Property1 + public string? Property1 { get => _property; set @@ -135,7 +135,7 @@ public string Property1 } } - public string Property2 + public string? Property2 { get => _property2; set @@ -145,7 +145,7 @@ public string Property2 } } - public void OnPropertyChanged([CallerMemberName] string propertyName = null) + public void OnPropertyChanged([CallerMemberName] string? propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } @@ -153,13 +153,13 @@ public void OnPropertyChanged([CallerMemberName] string propertyName = null) private class TestClassChanging : INotifyPropertyChanging { - private string _property1; + private string? _property1; - private string _property2; + private string? _property2; - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; - public string Property1 + public string? Property1 { get => _property1; set @@ -169,7 +169,7 @@ public string Property1 } } - public string Property2 + public string? Property2 { get => _property2; set @@ -179,7 +179,7 @@ public string Property2 } } - public void OnPropertyChanging([CallerMemberName] string propertyName = null) + public void OnPropertyChanging([CallerMemberName] string? propertyName = null) { var handler = PropertyChanging; handler?.Invoke(this, new PropertyChangingEventArgs(propertyName)); diff --git a/src/ReactiveUI.Tests/Resolvers/PocoObservableForPropertyTests.cs b/src/ReactiveUI.Tests/Resolvers/PocoObservableForPropertyTests.cs index 3287d33f4f..84da759860 100644 --- a/src/ReactiveUI.Tests/Resolvers/PocoObservableForPropertyTests.cs +++ b/src/ReactiveUI.Tests/Resolvers/PocoObservableForPropertyTests.cs @@ -18,15 +18,15 @@ namespace ReactiveUI.Tests { public class PocoObservableForPropertyTests { - private static TestLogger _testLoggerForNotificationPocoErrorOnBind; + private static TestLogger? _testLoggerForNotificationPocoErrorOnBind; [Fact] public void CheckGetAffinityForObjectValues() { var instance = new POCOObservableForProperty(); - Assert.Equal(1, instance.GetAffinityForObject(typeof(PocoType), null, false)); - Assert.Equal(1, instance.GetAffinityForObject(typeof(INPCClass), null, false)); + Assert.Equal(1, instance.GetAffinityForObject(typeof(PocoType), null!, false)); + Assert.Equal(1, instance.GetAffinityForObject(typeof(INPCClass), null!, false)); } [Fact] @@ -49,7 +49,7 @@ public void NotificationPocoErrorOnBind() var testClass = new PocoType(); - Expression> expr = x => x.Property1; + Expression> expr = x => x.Property1!; var exp = Reflection.Rewrite(expr.Body); instance.GetNotificationForProperty(testClass, exp, exp.GetMemberInfo().Name, false).Subscribe(_ => { }); @@ -79,7 +79,7 @@ public void NotificationPocoSuppressErrorOnBind() var testClass = new PocoType(); - Expression> expr = x => x.Property1; + Expression> expr = x => x.Property1!; var exp = Reflection.Rewrite(expr.Body); instance.GetNotificationForProperty(testClass, exp, exp.GetMemberInfo().Name, false, true).Subscribe(_ => { }); @@ -90,15 +90,15 @@ public void NotificationPocoSuppressErrorOnBind() private class PocoType { - public string Property1 { get; set; } + public string? Property1 { get; set; } - public string Property2 { get; set; } + public string? Property2 { get; set; } } #pragma warning disable CA1812 // Class is not instantiated private class INPCClass : INotifyPropertyChanged { - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; public void NotifyPropertyChanged() => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty)); } @@ -140,7 +140,7 @@ public TestLoggerRegistration() { } - public TestLoggerRegistration(TestLogger testLogger) + public TestLoggerRegistration(TestLogger? testLogger) { _originalLoggers = Locator.Current.GetServices().ToList(); diff --git a/src/ReactiveUI.Tests/Routing/Mocks/TestScreen.cs b/src/ReactiveUI.Tests/Routing/Mocks/TestScreen.cs index e221fd9a03..ff8d64ecf5 100644 --- a/src/ReactiveUI.Tests/Routing/Mocks/TestScreen.cs +++ b/src/ReactiveUI.Tests/Routing/Mocks/TestScreen.cs @@ -13,11 +13,13 @@ namespace ReactiveUI.Tests { public class TestScreen : ReactiveObject, IScreen { - private RoutingState _router; + private RoutingState? _router; - public RoutingState Router + public RoutingState? Router { +#pragma warning disable CS8766 // Nullability of reference types in return type doesn't match implicitly implemented member (possibly because of nullability attributes). get => _router; +#pragma warning restore CS8766 // Nullability of reference types in return type doesn't match implicitly implemented member (possibly because of nullability attributes). set => this.RaiseAndSetIfChanged(ref _router, value); } } diff --git a/src/ReactiveUI.Tests/Routing/Mocks/TestViewModel.cs b/src/ReactiveUI.Tests/Routing/Mocks/TestViewModel.cs index e656f9f720..2a71469210 100644 --- a/src/ReactiveUI.Tests/Routing/Mocks/TestViewModel.cs +++ b/src/ReactiveUI.Tests/Routing/Mocks/TestViewModel.cs @@ -13,9 +13,9 @@ namespace ReactiveUI.Tests { public class TestViewModel : ReactiveObject, IRoutableViewModel { - private string _someProp; + private string? _someProp; - public string SomeProp + public string? SomeProp { get => _someProp; set => this.RaiseAndSetIfChanged(ref _someProp, value); @@ -23,6 +23,6 @@ public string SomeProp public string UrlPathSegment => "Test"; - public IScreen HostScreen => null; + public IScreen HostScreen { get; } = new TestScreen(); } } diff --git a/src/ReactiveUI.Tests/Routing/RoutingStateTests.cs b/src/ReactiveUI.Tests/Routing/RoutingStateTests.cs index 8c6d7a3f4d..2eea2a37fd 100644 --- a/src/ReactiveUI.Tests/Routing/RoutingStateTests.cs +++ b/src/ReactiveUI.Tests/Routing/RoutingStateTests.cs @@ -62,7 +62,7 @@ public void CurrentViewModelObservableIsAccurate() public void CurrentViewModelObservableIsAccurateViaWhenAnyObservable() { var fixture = new TestScreen(); - fixture.WhenAnyObservable(x => x.Router.CurrentViewModel).ToObservableChangeSet(ImmediateScheduler.Instance).Bind(out var output).Subscribe(); + fixture.WhenAnyObservable(x => x.Router!.CurrentViewModel).ToObservableChangeSet(ImmediateScheduler.Instance).Bind(out var output).Subscribe(); fixture.Router = new RoutingState(); Assert.Equal(1, output.Count); diff --git a/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs b/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs index 21ef0b7b2b..bda9791d6d 100644 --- a/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs +++ b/src/ReactiveUI.Tests/Utilities/ApiApprovalBase.cs @@ -27,12 +27,17 @@ public abstract class ApiApprovalBase { private static readonly Regex _removeCoverletSectionRegex = new Regex(@"^namespace Coverlet\.Core\.Instrumentation\.Tracker.*?^}", RegexOptions.Singleline | RegexOptions.Multiline | RegexOptions.Compiled); - protected static void CheckApproval(Assembly assembly, [CallerMemberName]string memberName = null, [CallerFilePath]string filePath = null) + protected static void CheckApproval(Assembly assembly, [CallerMemberName]string? memberName = null, [CallerFilePath]string? filePath = null) { var targetFrameworkName = Assembly.GetExecutingAssembly().GetTargetFrameworkName(); var sourceDirectory = Path.GetDirectoryName(filePath); + if (sourceDirectory == null) + { + throw new ArgumentNullException(filePath); + } + var approvedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.approved.txt"); var receivedFileName = Path.Combine(sourceDirectory, $"ApiApprovalTests.{memberName}.{targetFrameworkName}.received.txt"); diff --git a/src/ReactiveUI.Tests/Utilities/EnumerableTestMixin.cs b/src/ReactiveUI.Tests/Utilities/EnumerableTestMixin.cs index 26172542ac..790a9ce96c 100644 --- a/src/ReactiveUI.Tests/Utilities/EnumerableTestMixin.cs +++ b/src/ReactiveUI.Tests/Utilities/EnumerableTestMixin.cs @@ -51,6 +51,11 @@ public static IEnumerable DistinctUntilChanged(this IEnumerable @this) continue; } + if (lastValue == null) + { + continue; + } + if (!EqualityComparer.Default.Equals(v, lastValue)) { yield return v; diff --git a/src/ReactiveUI.Tests/Utilities/JsonHelper.cs b/src/ReactiveUI.Tests/Utilities/JsonHelper.cs index f5ea81645d..020d450ee8 100644 --- a/src/ReactiveUI.Tests/Utilities/JsonHelper.cs +++ b/src/ReactiveUI.Tests/Utilities/JsonHelper.cs @@ -14,17 +14,29 @@ namespace ReactiveUI.Tests { public static class JSONHelper { - public static string Serialize(T serializeObject) + public static string? Serialize(T serializeObject) { + if (serializeObject == null) + { + return null; + } + var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(serializeObject.GetType()); var ms = new MemoryStream(); serializer.WriteObject(ms, serializeObject); return Encoding.Default.GetString(ms.ToArray()); } - public static T Deserialize(string json) + public static T? Deserialize(string json) + where T : class { var obj = Activator.CreateInstance(); + + if (obj == null) + { + return default; + } + var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)); var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType()); obj = (T)serializer.ReadObject(ms); diff --git a/src/ReactiveUI.Tests/Utilities/UseInvariantCulture.cs b/src/ReactiveUI.Tests/Utilities/UseInvariantCulture.cs index dcd7b217c6..467711e770 100644 --- a/src/ReactiveUI.Tests/Utilities/UseInvariantCulture.cs +++ b/src/ReactiveUI.Tests/Utilities/UseInvariantCulture.cs @@ -11,6 +11,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; + using Xunit.Sdk; namespace ReactiveUI.Tests @@ -18,7 +19,7 @@ namespace ReactiveUI.Tests // run tests on invariant culture to avoid problems e.g with culture specific decimal separator public class UseInvariantCulture : BeforeAfterTestAttribute { - private CultureInfo _storedCulture; + private CultureInfo? _storedCulture; public override void Before(MethodInfo methodUnderTest) { @@ -28,7 +29,10 @@ public override void Before(MethodInfo methodUnderTest) public override void After(MethodInfo methodUnderTest) { - Thread.CurrentThread.CurrentCulture = _storedCulture; + if (_storedCulture != null) + { + Thread.CurrentThread.CurrentCulture = _storedCulture; + } } } } diff --git a/src/ReactiveUI.Tests/WaitForDispatcherSchedulerTests.cs b/src/ReactiveUI.Tests/WaitForDispatcherSchedulerTests.cs index 99e354c72d..217440f87e 100644 --- a/src/ReactiveUI.Tests/WaitForDispatcherSchedulerTests.cs +++ b/src/ReactiveUI.Tests/WaitForDispatcherSchedulerTests.cs @@ -21,7 +21,7 @@ public void CallSchedulerFactoryOnCreation() () => { schedulerFactoryCalls++; - return null; + return null!; }); var sut = new WaitForDispatcherScheduler(schedulerFactory); @@ -32,14 +32,14 @@ public void CallSchedulerFactoryOnCreation() [Fact] public void FactoryThrowsArgumentNullException_FallsBackToCurrentThread() { - IScheduler schedulerExecutedOn = null; + IScheduler? schedulerExecutedOn = null; #pragma warning disable CA2208 // Instantiate argument exceptions correctly var schedulerFactory = new Func(() => throw new ArgumentNullException()); #pragma warning restore CA2208 // Instantiate argument exceptions correctly var sut = new WaitForDispatcherScheduler(schedulerFactory); sut.Schedule( - null, + null!, (scheduler, state) => { schedulerExecutedOn = scheduler; @@ -69,12 +69,12 @@ public void FactoryThrowsException_ReCallsOnSchedule() [Fact] public void FactoryThrowsInvalidOperationException_FallsBackToCurrentThread() { - IScheduler schedulerExecutedOn = null; + IScheduler schedulerExecutedOn = null!; var schedulerFactory = new Func(() => throw new InvalidOperationException()); var sut = new WaitForDispatcherScheduler(schedulerFactory); sut.Schedule( - null, + null!, (scheduler, state) => { schedulerExecutedOn = scheduler; diff --git a/src/ReactiveUI.Tests/WhenAny/Mockups/HostTestFixture.cs b/src/ReactiveUI.Tests/WhenAny/Mockups/HostTestFixture.cs index 76195770ac..c0d99f3e1a 100644 --- a/src/ReactiveUI.Tests/WhenAny/Mockups/HostTestFixture.cs +++ b/src/ReactiveUI.Tests/WhenAny/Mockups/HostTestFixture.cs @@ -7,19 +7,19 @@ namespace ReactiveUI.Tests { public class HostTestFixture : ReactiveObject { - private TestFixture _Child; + private TestFixture? _Child; - private NonObservableTestFixture _PocoChild; + private NonObservableTestFixture? _PocoChild; private int _SomeOtherParam; - public TestFixture Child + public TestFixture? Child { get => _Child; set => this.RaiseAndSetIfChanged(ref _Child, value); } - public NonObservableTestFixture PocoChild + public NonObservableTestFixture? PocoChild { get => _PocoChild; set => this.RaiseAndSetIfChanged(ref _PocoChild, value); diff --git a/src/ReactiveUI.Tests/WhenAny/Mockups/NonObservableTestFixture.cs b/src/ReactiveUI.Tests/WhenAny/Mockups/NonObservableTestFixture.cs index 4c2143c333..17d121c3d7 100644 --- a/src/ReactiveUI.Tests/WhenAny/Mockups/NonObservableTestFixture.cs +++ b/src/ReactiveUI.Tests/WhenAny/Mockups/NonObservableTestFixture.cs @@ -7,6 +7,6 @@ namespace ReactiveUI.Tests { public class NonObservableTestFixture { - public TestFixture Child { get; set; } + public TestFixture? Child { get; set; } } } diff --git a/src/ReactiveUI.Tests/WhenAny/Mockups/NonReactiveINPCObject.cs b/src/ReactiveUI.Tests/WhenAny/Mockups/NonReactiveINPCObject.cs index 1c7bd92e01..fdcce393d8 100644 --- a/src/ReactiveUI.Tests/WhenAny/Mockups/NonReactiveINPCObject.cs +++ b/src/ReactiveUI.Tests/WhenAny/Mockups/NonReactiveINPCObject.cs @@ -9,9 +9,9 @@ namespace ReactiveUI.Tests { public class NonReactiveINPCObject : INotifyPropertyChanged { - private TestFixture _inpcProperty; + private TestFixture _inpcProperty = new TestFixture(); - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; public TestFixture InpcProperty { @@ -29,4 +29,4 @@ public TestFixture InpcProperty } } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs b/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs index 0ecda0d91d..a78235cf08 100644 --- a/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs +++ b/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs @@ -60,18 +60,18 @@ public void MultiPropertyExpressionsShouldBeProperlyResolved() { var data = new Dictionary>, string[]> { - { x => x.Child.IsOnlyOneWord.Length, new[] { "Child", "IsOnlyOneWord", "Length" } }, + { x => x!.Child!.IsOnlyOneWord!.Length, new[] { "Child", "IsOnlyOneWord", "Length" } }, { x => x.SomeOtherParam, new[] { "SomeOtherParam" } }, - { x => x.Child.IsNotNullString, new[] { "Child", "IsNotNullString" } }, - { x => x.Child.Changed, new[] { "Child", "Changed" } }, + { x => x.Child!.IsNotNullString!, new[] { "Child", "IsNotNullString" } }, + { x => x.Child!.Changed, new[] { "Child", "Changed" } }, }; var dataTypes = new Dictionary>, Type[]> { - { x => x.Child.IsOnlyOneWord.Length, new[] { typeof(TestFixture), typeof(string), typeof(int) } }, + { x => x.Child!.IsOnlyOneWord!.Length, new[] { typeof(TestFixture), typeof(string), typeof(int) } }, { x => x.SomeOtherParam, new[] { typeof(int) } }, - { x => x.Child.IsNotNullString, new[] { typeof(TestFixture), typeof(string) } }, - { x => x.Child.Changed, new[] { typeof(TestFixture), typeof(IObservable>) } }, + { x => x.Child!.IsNotNullString!, new[] { typeof(TestFixture), typeof(string) } }, + { x => x.Child!.Changed, new[] { typeof(TestFixture), typeof(IObservable>) } }, }; var results = data.Keys.Select( @@ -107,7 +107,7 @@ public void OFPChangingTheHostPropertyShouldFireAChildChangeNotificationOnlyIfTh { Child = new TestFixture() }; - fixture.ObservableForProperty(x => x.Child.IsOnlyOneWord) + fixture.ObservableForProperty(x => x.Child!.IsOnlyOneWord) .ToObservableChangeSet(ImmediateScheduler.Instance) .Bind(out var changes) .Subscribe(); @@ -262,7 +262,7 @@ public void OFPReplacingTheHostShouldResubscribeTheObservable() { Child = new TestFixture() }; - fixture.ObservableForProperty(x => x.Child.IsOnlyOneWord) + fixture.ObservableForProperty(x => x.Child!.IsOnlyOneWord) .ToObservableChangeSet(ImmediateScheduler.Instance) .Bind(out var changes) .Subscribe(); @@ -282,7 +282,7 @@ public void OFPReplacingTheHostShouldResubscribeTheObservable() Assert.Equal(3, changes.Count); // Here we've set the value but it shouldn't change - fixture.Child.IsOnlyOneWord = null; + fixture.Child.IsOnlyOneWord = null!; sched.Start(); Assert.Equal(3, changes.Count); @@ -309,7 +309,7 @@ public void OFPReplacingTheHostWithNullThenSettingItBackShouldResubscribeTheObse { Child = new TestFixture() }; - fixture.ObservableForProperty(x => x.Child.IsOnlyOneWord) + fixture.ObservableForProperty(x => x.Child!.IsOnlyOneWord) .ToObservableChangeSet(ImmediateScheduler.Instance) .Bind(out var changes) .Subscribe(); @@ -323,7 +323,7 @@ public void OFPReplacingTheHostWithNullThenSettingItBackShouldResubscribeTheObse Assert.Equal(2, changes.Count); // Oops, now the child is Null, we may now blow up - fixture.Child = null; + fixture.Child = null!; sched.Start(); Assert.Equal(2, changes.Count); @@ -346,7 +346,7 @@ public void OFPShouldWorkWithINPCObjectsToo() { var fixture = new NonReactiveINPCObject { - InpcProperty = null + InpcProperty = null! }; fixture.ObservableForProperty(x => x.InpcProperty.IsOnlyOneWord) .ToObservableChangeSet(ImmediateScheduler.Instance) @@ -376,7 +376,7 @@ public void OFPSimpleChildPropertyTest() { Child = new TestFixture() }; - fixture.ObservableForProperty(x => x.Child.IsOnlyOneWord) + fixture.ObservableForProperty(x => x.Child!.IsOnlyOneWord) .ToObservableChangeSet(ImmediateScheduler.Instance) .Bind(out var changes) .Subscribe(); @@ -487,9 +487,9 @@ public void WhenAnyShouldWorkEvenWithNormalProperties() PocoProperty = "Bamf" }; - var output = new List>(); + var output = new List>(); fixture.WhenAny(x => x.PocoProperty, x => x).Subscribe(output.Add); - var output2 = new List(); + var output2 = new List(); fixture.WhenAnyValue(x => x.PocoProperty).Subscribe(output2.Add); var output3 = new List>(); fixture.WhenAny(x => x.NullableInt, x => x).Subscribe(output3.Add); @@ -524,8 +524,8 @@ public void ChangedShouldHaveValidData() PocoProperty = "Bamf" }; - object sender = null; - string propertyName = null; + object sender = null!; + string? propertyName = null; fixture.Changed.ObserveOn(ImmediateScheduler.Instance).Subscribe( x => { @@ -538,11 +538,11 @@ public void ChangedShouldHaveValidData() Assert.Equal(fixture, sender); Assert.Equal(nameof(fixture.UsesExprRaiseSet), propertyName); - sender = null; + sender = null!; propertyName = null; fixture.PocoProperty = "abc"; - Assert.Equal(null, sender); + Assert.Equal(null!, sender); Assert.Equal(null, propertyName); } @@ -556,8 +556,8 @@ public void ChangingShouldHaveValidData() PocoProperty = "Bamf" }; - object sender = null; - string propertyName = null; + object sender = null!; + string? propertyName = null; fixture.Changing.ObserveOn(ImmediateScheduler.Instance).Subscribe( x => { @@ -570,11 +570,11 @@ public void ChangingShouldHaveValidData() Assert.Equal(fixture, sender); Assert.Equal(nameof(fixture.UsesExprRaiseSet), propertyName); - sender = null; + sender = null!; propertyName = null; fixture.PocoProperty = "abc"; - Assert.Equal(null, sender); + Assert.Equal(null!, sender); Assert.Equal(null, propertyName); } @@ -595,7 +595,7 @@ public void WhenAnySmokeTest() var output2 = new List>(); fixture.WhenAny( x => x.SomeOtherParam, - x => x.Child.IsNotNullString, + x => x.Child!.IsNotNullString, (sop, nns) => new { sop, @@ -604,7 +604,7 @@ public void WhenAnySmokeTest() x => { output1.Add(x.sop); - output2.Add(x.nns); + output2.Add(x.nns!); }); sched.Start(); @@ -645,10 +645,10 @@ public void WhenAnyValueShouldWorkEvenWithNormalProperties() PocoProperty = "Bamf" }; - var output1 = new List(); + var output1 = new List(); var output2 = new List(); fixture.WhenAnyValue(x => x.PocoProperty).Subscribe(output1.Add); - fixture.WhenAnyValue(x => x.IsOnlyOneWord, x => x.Length).Subscribe(output2.Add); + fixture.WhenAnyValue(x => x.IsOnlyOneWord, x => x!.Length).Subscribe(output2.Add); Assert.Equal(1, output1.Count); Assert.Equal("Bamf", output1[0]); @@ -673,7 +673,7 @@ public void WhenAnyValueSmokeTest() var output2 = new List(); fixture.WhenAnyValue( x => x.SomeOtherParam, - x => x.Child.IsNotNullString, + x => x.Child!.IsNotNullString, (sop, nns) => new { sop, @@ -682,7 +682,7 @@ public void WhenAnyValueSmokeTest() x => { output1.Add(x.sop); - output2.Add(x.nns); + output2.Add(x.nns!); }); sched.Start(); diff --git a/src/ReactiveUI.Tests/WhenAny/TestWhenAnyObsViewModel.cs b/src/ReactiveUI.Tests/WhenAny/TestWhenAnyObsViewModel.cs index c6ac9e965e..fd7a6a759a 100644 --- a/src/ReactiveUI.Tests/WhenAny/TestWhenAnyObsViewModel.cs +++ b/src/ReactiveUI.Tests/WhenAny/TestWhenAnyObsViewModel.cs @@ -13,9 +13,9 @@ namespace ReactiveUI.Tests { public class TestWhenAnyObsViewModel : ReactiveObject { - private IObservable> _changes; + private IObservable>? _changes; - private ObservableCollectionExtended _myListOfInts; + private ObservableCollectionExtended? _myListOfInts; public TestWhenAnyObsViewModel() { @@ -24,20 +24,20 @@ public TestWhenAnyObsViewModel() Command3 = ReactiveCommand.CreateFromObservable(Observable.Return, outputScheduler: ImmediateScheduler.Instance); } - public IObservable> Changes + public IObservable>? Changes { get => _changes; set => this.RaiseAndSetIfChanged(ref _changes, value); } - public ReactiveCommand Command1 { get; set; } + public ReactiveCommand? Command1 { get; set; } public ReactiveCommand Command2 { get; set; } public ReactiveCommand Command3 { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Test usage")] - public ObservableCollectionExtended MyListOfInts + public ObservableCollectionExtended? MyListOfInts { get => _myListOfInts; set diff --git a/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs b/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs index 9d8b280d92..8947ae2699 100644 --- a/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs +++ b/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs @@ -60,7 +60,7 @@ public async Task WhenAnyObservableSmokeTestCombining() Assert.Equal(0, list.Count); - await fixture.Command1.Execute(1); + await fixture.Command1!.Execute(1); await fixture.Command3.Execute("foo"); Assert.Equal(1, list.Count); @@ -90,7 +90,7 @@ public async Task WhenAnyObservableSmokeTestMerging() Assert.Equal(0, list.Count); - await fixture.Command1.Execute(1); + await fixture.Command1!.Execute(1); Assert.Equal(1, list.Count); await fixture.Command2.Execute(2); diff --git a/src/ReactiveUI.Uno/ReactiveUI.Uno.csproj b/src/ReactiveUI.Uno/ReactiveUI.Uno.csproj index 48337c1ce1..037f0f4cdc 100644 --- a/src/ReactiveUI.Uno/ReactiveUI.Uno.csproj +++ b/src/ReactiveUI.Uno/ReactiveUI.Uno.csproj @@ -6,6 +6,7 @@ Contains the ReactiveUI platform specific extensions for Uno HAS_UNO $(NoWarn);SA1648;CA1816;CA1001;CS0108;CS0114;CS3021;CS1574;CA1303 + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;net;unoplatform diff --git a/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs b/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs index 97f6acd4ff..8babc003b5 100644 --- a/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs +++ b/src/ReactiveUI.Winforms/ActivationForViewFetcher.cs @@ -42,29 +42,17 @@ public IObservable GetActivationForView(IActivatableView view) } var handleDestroyed = Observable.FromEvent( - eventHandler => - { - void Handler(object sender, EventArgs e) => eventHandler(false); - return Handler; - }, + eventHandler => (sender, e) => eventHandler(false), h => control.HandleDestroyed += h, h => control.HandleDestroyed -= h); var handleCreated = Observable.FromEvent( - eventHandler => - { - void Handler(object sender, EventArgs e) => eventHandler(true); - return Handler; - }, + eventHandler => (sender, e) => eventHandler(true), h => control.HandleCreated += h, h => control.HandleCreated -= h); var visibleChanged = Observable.FromEvent( - eventHandler => - { - void Handler(object sender, EventArgs e) => eventHandler(control.Visible); - return Handler; - }, + eventHandler => (sender, e) => eventHandler(control.Visible), h => control.VisibleChanged += h, h => control.VisibleChanged -= h); diff --git a/src/ReactiveUI.Winforms/CreatesWinformsCommandBinding.cs b/src/ReactiveUI.Winforms/CreatesWinformsCommandBinding.cs index 47b5799612..f0bf92d505 100644 --- a/src/ReactiveUI.Winforms/CreatesWinformsCommandBinding.cs +++ b/src/ReactiveUI.Winforms/CreatesWinformsCommandBinding.cs @@ -52,7 +52,7 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// - public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter) + public IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter) { if (target == null) { @@ -74,11 +74,11 @@ public IDisposable BindCommandToObject(ICommand command, object target, IObserva var mi = GetType().GetMethods().First(x => x.Name == "BindCommandToObject" && x.IsGenericMethod); mi = mi.MakeGenericMethod(eventInfo.Args); - return (IDisposable)mi.Invoke(this, new[] { command, target, commandParameter, eventInfo.EventInfo.Name }); + return (IDisposable?)mi.Invoke(this, new[] { command, target, commandParameter, eventInfo.EventInfo?.Name }); } /// - public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) + public IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) { if (command == null) { @@ -92,7 +92,7 @@ public IDisposable BindCommandToObject(ICommand command, object targ var ret = new CompositeDisposable(); - object latestParameter = null; + object? latestParameter = null; Type targetType = target.GetType(); ret.Add(commandParameter.Subscribe(x => latestParameter = x)); @@ -112,19 +112,15 @@ public IDisposable BindCommandToObject(ICommand command, object targ // For example: System.Windows.Forms.ToolStripButton. if (typeof(Component).IsAssignableFrom(targetType)) { - PropertyInfo enabledProperty = targetType.GetRuntimeProperty("Enabled"); + PropertyInfo? enabledProperty = targetType.GetRuntimeProperty("Enabled"); if (enabledProperty != null) { - object latestParam = null; + object? latestParam = null; ret.Add(commandParameter.Subscribe(x => latestParam = x)); ret.Add(Observable.FromEvent( - eventHandler => - { - void Handler(object sender, EventArgs e) => eventHandler(command.CanExecute(latestParam)); - return Handler; - }, + eventHandler => (sender, e) => eventHandler(command.CanExecute(latestParam)), x => command.CanExecuteChanged += x, x => command.CanExecuteChanged -= x) .StartWith(command.CanExecute(latestParam)) diff --git a/src/ReactiveUI.Winforms/PanelSetMethodBindingConverter.cs b/src/ReactiveUI.Winforms/PanelSetMethodBindingConverter.cs index a390e0a3e5..b4c22d3bd0 100644 --- a/src/ReactiveUI.Winforms/PanelSetMethodBindingConverter.cs +++ b/src/ReactiveUI.Winforms/PanelSetMethodBindingConverter.cs @@ -35,14 +35,21 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public object PerformSet(object toTarget, object newValue, object[] arguments) + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "Valid syntax.")] + public object PerformSet(object? toTarget, object? newValue, object[]? arguments) { if (toTarget == null) { throw new ArgumentNullException(nameof(toTarget)); } - IEnumerable newValueEnumerable = (IEnumerable)newValue; + IEnumerable? newValueEnumerable = newValue as IEnumerable; + + if (newValueEnumerable == null) + { + throw new ArgumentException($"newValue must be {nameof(newValue)}", nameof(newValue)); + } + Control.ControlCollection targetCollection = (Control.ControlCollection)toTarget; targetCollection.Owner.SuspendLayout(); diff --git a/src/ReactiveUI.Winforms/PlatformOperations.cs b/src/ReactiveUI.Winforms/PlatformOperations.cs index 23106a377e..efa078625b 100644 --- a/src/ReactiveUI.Winforms/PlatformOperations.cs +++ b/src/ReactiveUI.Winforms/PlatformOperations.cs @@ -17,7 +17,7 @@ namespace ReactiveUI.Winforms public class PlatformOperations : IPlatformOperations { /// - public string GetOrientation() + public string? GetOrientation() { return null; } diff --git a/src/ReactiveUI.Winforms/ReactiveUI.Winforms.csproj b/src/ReactiveUI.Winforms/ReactiveUI.Winforms.csproj index 80d2443f17..f5aeb34f8d 100644 --- a/src/ReactiveUI.Winforms/ReactiveUI.Winforms.csproj +++ b/src/ReactiveUI.Winforms/ReactiveUI.Winforms.csproj @@ -7,6 +7,7 @@ Contains the ReactiveUI platform specific extensions for Windows Forms ReactiveUI.WinForms true + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;winforms;net;net461; diff --git a/src/ReactiveUI.Winforms/ReactiveUserControl.cs b/src/ReactiveUI.Winforms/ReactiveUserControl.cs index c8a69e2251..77b3c7e2ad 100644 --- a/src/ReactiveUI.Winforms/ReactiveUserControl.cs +++ b/src/ReactiveUI.Winforms/ReactiveUserControl.cs @@ -31,13 +31,13 @@ public ReactiveUserControl() [Description("The ViewModel.")] [Bindable(true)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - public TViewModel ViewModel { get; set; } + public TViewModel? ViewModel { get; set; } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.Winforms/RoutedViewHost.cs b/src/ReactiveUI.Winforms/RoutedViewHost.cs index 7f068d1a2d..83995910db 100644 --- a/src/ReactiveUI.Winforms/RoutedViewHost.cs +++ b/src/ReactiveUI.Winforms/RoutedViewHost.cs @@ -18,9 +18,9 @@ namespace ReactiveUI.Winforms public partial class RoutedControlHost : UserControl, IReactiveObject { private readonly CompositeDisposable _disposables = new CompositeDisposable(); - private RoutingState _router; - private Control _defaultContent; - private IObservable _viewContractObservable; + private RoutingState? _router; + private Control? _defaultContent; + private IObservable? _viewContractObservable; /// /// Initializes a new instance of the class. @@ -41,12 +41,12 @@ public RoutedControlHost() ViewContractObservable = Observable.Default; var vmAndContract = - this.WhenAnyObservable(x => x.Router.CurrentViewModel) + this.WhenAnyObservable(x => x.Router!.CurrentViewModel!) .CombineLatest( - this.WhenAnyObservable(x => x.ViewContractObservable), + this.WhenAnyObservable(x => x.ViewContractObservable!), (vm, contract) => new { ViewModel = vm, Contract = contract }); - Control viewLastAdded = null; + Control viewLastAdded = null!; _disposables.Add(vmAndContract.Subscribe( x => { @@ -72,20 +72,24 @@ public RoutedControlHost() } IViewLocator viewLocator = ViewLocator ?? ReactiveUI.ViewLocator.Current; - IViewFor view = viewLocator.ResolveView(x.ViewModel, x.Contract); - view.ViewModel = x.ViewModel; + IViewFor? view = viewLocator.ResolveView(x.ViewModel, x.Contract); + if (view != null) + { + view.ViewModel = x.ViewModel; + + viewLastAdded = InitView((Control)view); + } - viewLastAdded = InitView((Control)view); Controls.Add(viewLastAdded); ResumeLayout(); - }, RxApp.DefaultExceptionHandler.OnNext)); + }, RxApp.DefaultExceptionHandler!.OnNext)); } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// /// Gets or sets the default content. @@ -95,7 +99,7 @@ public RoutedControlHost() /// [Category("ReactiveUI")] [Description("The default control when no viewmodel is specified")] - public Control DefaultContent + public Control? DefaultContent { get => _defaultContent; set => this.RaiseAndSetIfChanged(ref _defaultContent, value); @@ -106,7 +110,7 @@ public Control DefaultContent /// [Category("ReactiveUI")] [Description("The router.")] - public RoutingState Router + public RoutingState? Router { get => _router; set => this.RaiseAndSetIfChanged(ref _router, value); @@ -116,7 +120,7 @@ public RoutingState Router /// Gets or sets the view contract observable. /// [Browsable(false)] - public IObservable ViewContractObservable + public IObservable? ViewContractObservable { get => _viewContractObservable; set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); @@ -126,7 +130,7 @@ public IObservable ViewContractObservable /// Gets or sets the view locator. /// [Browsable(false)] - public IViewLocator ViewLocator { get; set; } + public IViewLocator? ViewLocator { get; set; } /// void IReactiveObject.RaisePropertyChanging(PropertyChangingEventArgs args) diff --git a/src/ReactiveUI.Winforms/TableContentSetMethodBindingConverter.cs b/src/ReactiveUI.Winforms/TableContentSetMethodBindingConverter.cs index 8c79a0fa82..2249e57366 100644 --- a/src/ReactiveUI.Winforms/TableContentSetMethodBindingConverter.cs +++ b/src/ReactiveUI.Winforms/TableContentSetMethodBindingConverter.cs @@ -6,8 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Forms; namespace ReactiveUI.Winforms @@ -34,7 +32,8 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public object PerformSet(object toTarget, object newValue, object[] arguments) + [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "Valid syntax.")] + public object PerformSet(object? toTarget, object? newValue, object[]? arguments) { if (toTarget == null) { @@ -43,10 +42,15 @@ public object PerformSet(object toTarget, object newValue, object[] arguments) if (!(toTarget is TableLayoutControlCollection targetCollection)) { - throw new ArgumentException($"{nameof(toTarget)} must be of type {nameof(TableLayoutControlCollection)}"); + throw new ArgumentException($"{nameof(toTarget)} must be of type {nameof(TableLayoutControlCollection)}", nameof(toTarget)); } - IEnumerable newValueEnumerable = (IEnumerable)newValue; + IEnumerable? newValueEnumerable = newValue as IEnumerable; + + if (newValueEnumerable == null) + { + throw new ArgumentException($"newValue must be {nameof(newValue)}", nameof(newValue)); + } targetCollection.Container.SuspendLayout(); diff --git a/src/ReactiveUI.Winforms/ViewModelViewHost.cs b/src/ReactiveUI.Winforms/ViewModelViewHost.cs index a91343daad..08f525fa2b 100644 --- a/src/ReactiveUI.Winforms/ViewModelViewHost.cs +++ b/src/ReactiveUI.Winforms/ViewModelViewHost.cs @@ -19,10 +19,10 @@ namespace ReactiveUI.Winforms public partial class ViewModelControlHost : UserControl, IReactiveObject, IViewFor { private readonly CompositeDisposable _disposables = new CompositeDisposable(); - private Control _defaultContent; - private IObservable _viewContractObservable; - private object _viewModel; - private object _content; + private Control? _defaultContent; + private IObservable? _viewContractObservable; + private object? _viewModel; + private object? _content; private bool _cacheViews; /// @@ -40,10 +40,10 @@ public ViewModelControlHost() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// /// Gets or sets a value indicating whether [default cache views enabled]. @@ -53,14 +53,14 @@ public ViewModelControlHost() /// /// Gets the current view. /// - public Control CurrentView => _content as Control; + public Control? CurrentView => _content as Control; /// /// Gets or sets the default content. /// [Category("ReactiveUI")] [Description("The default control when no viewmodel is specified")] - public Control DefaultContent + public Control? DefaultContent { get => _defaultContent; set => this.RaiseAndSetIfChanged(ref _defaultContent, value); @@ -73,7 +73,7 @@ public Control DefaultContent /// The view contract observable. /// [Browsable(false)] - public IObservable ViewContractObservable + public IObservable? ViewContractObservable { get => _viewContractObservable; set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); @@ -83,13 +83,13 @@ public IObservable ViewContractObservable /// Gets or sets the view locator. /// [Browsable(false)] - public IViewLocator ViewLocator { get; set; } + public IViewLocator? ViewLocator { get; set; } /// [Category("ReactiveUI")] [Description("The viewmodel to host.")] [Bindable(true)] - public object ViewModel + public object? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); @@ -101,7 +101,7 @@ public object ViewModel [Category("ReactiveUI")] [Description("The Current View")] [Bindable(true)] - public object Content + public object? Content { get => _content; protected set => this.RaiseAndSetIfChanged(ref _content, value); @@ -150,22 +150,25 @@ protected override void Dispose(bool disposing) private IEnumerable SetupBindings() { var viewChanges = - this.WhenAnyValue(x => x.Content).Select(x => x as Control).Where(x => x != null).Subscribe(x => - { - // change the view in the ui - SuspendLayout(); - - // clear out existing visible control view - foreach (Control c in Controls) + this.WhenAnyValue(x => x.Content) + .Select(x => x as Control) + .Where(x => x != null) + .Subscribe(x => { - c.Dispose(); - Controls.Remove(c); - } + // change the view in the ui + SuspendLayout(); + + // clear out existing visible control view + foreach (Control? c in Controls) + { + c?.Dispose(); + Controls.Remove(c); + } - x.Dock = DockStyle.Fill; - Controls.Add(x); - ResumeLayout(); - }); + x!.Dock = DockStyle.Fill; + Controls.Add(x); + ResumeLayout(); + }); yield return viewChanges; @@ -182,7 +185,7 @@ private IEnumerable SetupBindings() var vmAndContract = this.WhenAny(x => x.ViewModel, x => x.Value) .CombineLatest( - this.WhenAnyObservable(x => x.ViewContractObservable), + this.WhenAnyObservable(x => x.ViewContractObservable!), (vm, contract) => new { ViewModel = vm, Contract = contract }); yield return vmAndContract.Subscribe( @@ -204,8 +207,7 @@ private IEnumerable SetupBindings() // when caching views, check the current viewmodel and type var c = _content as IViewFor; - if (c != null && c.ViewModel != null - && c.ViewModel.GetType() == x.ViewModel.GetType()) + if (c?.ViewModel != null && c.ViewModel.GetType() == x.ViewModel!.GetType()) { c.ViewModel = x.ViewModel; @@ -216,10 +218,13 @@ private IEnumerable SetupBindings() } IViewLocator viewLocator = ViewLocator ?? ReactiveUI.ViewLocator.Current; - IViewFor view = viewLocator.ResolveView(x.ViewModel, x.Contract); - view.ViewModel = x.ViewModel; - Content = view; - }, RxApp.DefaultExceptionHandler.OnNext); + IViewFor? view = viewLocator.ResolveView(x.ViewModel, x.Contract); + if (view != null) + { + view.ViewModel = x.ViewModel; + Content = view; + } + }, RxApp.DefaultExceptionHandler!.OnNext); } } } diff --git a/src/ReactiveUI.Wpf/AutoSuspendHelper.cs b/src/ReactiveUI.Wpf/AutoSuspendHelper.cs index 86ed1a6ed8..3d3fd883e5 100644 --- a/src/ReactiveUI.Wpf/AutoSuspendHelper.cs +++ b/src/ReactiveUI.Wpf/AutoSuspendHelper.cs @@ -45,11 +45,7 @@ public AutoSuspendHelper(Application app) RxApp.SuspensionHost.IsUnpausing = Observable.FromEvent( - eventHandler => - { - void Handler(object sender, EventArgs e) => eventHandler(Unit.Default); - return Handler; - }, + eventHandler => (sender, e) => eventHandler(Unit.Default), x => app.Activated += x, x => app.Activated -= x); @@ -58,11 +54,7 @@ public AutoSuspendHelper(Application app) // NB: No way to tell OS that we need time to suspend, we have to // do it in-process var deactivated = Observable.FromEvent( - eventHandler => - { - void Handler(object sender, EventArgs e) => eventHandler(Unit.Default); - return Handler; - }, + eventHandler => (sender, e) => eventHandler(Unit.Default), x => app.Deactivated += x, x => app.Deactivated -= x); diff --git a/src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs b/src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs index b645baa989..a3b3e78f16 100644 --- a/src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs +++ b/src/ReactiveUI.Wpf/DependencyObjectObservableForProperty.cs @@ -66,14 +66,14 @@ public IObservable> GetNotificationForProperty(o }); } - private static DependencyProperty GetDependencyProperty(Type type, string propertyName) + private static DependencyProperty? GetDependencyProperty(Type type, string propertyName) { var fi = type.GetTypeInfo().GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public) .FirstOrDefault(x => x.Name == propertyName + "Property" && x.IsStatic); if (fi != null) { - return (DependencyProperty)fi.GetValue(null); + return (DependencyProperty?)fi.GetValue(null); } return null; diff --git a/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj b/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj index 1eaec515d7..d7e8b00dd7 100644 --- a/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj +++ b/src/ReactiveUI.Wpf/ReactiveUI.Wpf.csproj @@ -4,6 +4,7 @@ Contains the ReactiveUI platform specific extensions for Windows Presentation Foundation (WPF) ReactiveUI.WPF true + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;wpf;net;net461 diff --git a/src/ReactiveUI.Wpf/ReactiveWindow.cs b/src/ReactiveUI.Wpf/ReactiveWindow.cs index dd9813855e..2f92b8ed02 100644 --- a/src/ReactiveUI.Wpf/ReactiveWindow.cs +++ b/src/ReactiveUI.Wpf/ReactiveWindow.cs @@ -56,20 +56,20 @@ public class ReactiveWindow : /// /// Gets the binding root view model. /// - public TViewModel BindingRoot => ViewModel; + public TViewModel? BindingRoot => ViewModel; /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } } } diff --git a/src/ReactiveUI.Wpf/TransitioningContentControl.cs b/src/ReactiveUI.Wpf/TransitioningContentControl.cs index a5f14a80b5..0e27840b1d 100644 --- a/src/ReactiveUI.Wpf/TransitioningContentControl.cs +++ b/src/ReactiveUI.Wpf/TransitioningContentControl.cs @@ -54,11 +54,11 @@ public class TransitioningContentControl : ContentControl private const string PresentationGroup = "PresentationStates"; private const string NormalState = "Normal"; private bool _isTransitioning; - private Storyboard _startingTransition; - private Storyboard _completingTransition; - private Grid _container; - private ContentPresenter _previousContentPresentationSite; - private ContentPresenter _currentContentPresentationSite; + private Storyboard? _startingTransition; + private Storyboard? _completingTransition; + private Grid? _container; + private ContentPresenter? _previousContentPresentationSite; + private ContentPresenter? _currentContentPresentationSite; /// /// Initializes a new instance of the class. @@ -71,12 +71,12 @@ public TransitioningContentControl() /// /// Occurs when a transition has completed. /// - public event RoutedEventHandler TransitionCompleted; + public event RoutedEventHandler? TransitionCompleted; /// /// Occurs when a transition has started. /// - public event RoutedEventHandler TransitionStarted; + public event RoutedEventHandler? TransitionStarted; /// /// Represents the type of transition that a TransitioningContentControl will perform. @@ -153,7 +153,7 @@ public enum TransitionDirection /// The duration. public TimeSpan Duration { get => (TimeSpan)GetValue(TransitionDurationProperty); set => SetValue(TransitionDurationProperty, value); } - private Storyboard StartingTransition + private Storyboard? StartingTransition { get => _startingTransition; set @@ -166,7 +166,7 @@ private Storyboard StartingTransition } } - private Storyboard CompletingTransition + private Storyboard? CompletingTransition { get => _completingTransition; set @@ -243,7 +243,7 @@ private void AbortTransition() } } - private void OnTransitionCompleted(object sender, EventArgs e) + private void OnTransitionCompleted(object? sender, EventArgs e) { AbortTransition(); @@ -328,65 +328,74 @@ private void SetTransitionDefaultValues() // Do some special handling of particular transitions so that we get nice smooth transitions that utilise the size of the content. if (Transition == TransitionType.Fade) { - var completingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[0]; - var startingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[1]; - startingDoubleAnimation.Duration = Duration; - completingDoubleAnimation.Duration = Duration; + if (CompletingTransition != null) + { + var completingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[0]; + var startingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[1]; + startingDoubleAnimation.Duration = Duration; + completingDoubleAnimation.Duration = Duration; + } } if (Transition == TransitionType.Slide) { - var startingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[0]; - startingDoubleAnimation.Duration = Duration; - if (Direction == TransitionDirection.Down) + if (CompletingTransition != null) { - startingDoubleAnimation.From = -ActualHeight; - } + var startingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[0]; + startingDoubleAnimation.Duration = Duration; + if (Direction == TransitionDirection.Down) + { + startingDoubleAnimation.From = -ActualHeight; + } - if (Direction == TransitionDirection.Up) - { - startingDoubleAnimation.From = ActualHeight; - } + if (Direction == TransitionDirection.Up) + { + startingDoubleAnimation.From = ActualHeight; + } - if (Direction == TransitionDirection.Right) - { - startingDoubleAnimation.From = -ActualWidth; - } + if (Direction == TransitionDirection.Right) + { + startingDoubleAnimation.From = -ActualWidth; + } - if (Direction == TransitionDirection.Left) - { - startingDoubleAnimation.From = ActualWidth; + if (Direction == TransitionDirection.Left) + { + startingDoubleAnimation.From = ActualWidth; + } } } if (Transition == TransitionType.Move) { - var completingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[0]; - var startingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[1]; - startingDoubleAnimation.Duration = Duration; - completingDoubleAnimation.Duration = Duration; - if (Direction == TransitionDirection.Down) + if (CompletingTransition != null) { - startingDoubleAnimation.To = ActualHeight; - completingDoubleAnimation.From = -ActualHeight; - } + var completingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[0]; + var startingDoubleAnimation = (DoubleAnimation)CompletingTransition.Children[1]; + startingDoubleAnimation.Duration = Duration; + completingDoubleAnimation.Duration = Duration; + if (Direction == TransitionDirection.Down) + { + startingDoubleAnimation.To = ActualHeight; + completingDoubleAnimation.From = -ActualHeight; + } - if (Direction == TransitionDirection.Up) - { - startingDoubleAnimation.To = -ActualHeight; - completingDoubleAnimation.From = ActualHeight; - } + if (Direction == TransitionDirection.Up) + { + startingDoubleAnimation.To = -ActualHeight; + completingDoubleAnimation.From = ActualHeight; + } - if (Direction == TransitionDirection.Right) - { - startingDoubleAnimation.To = ActualWidth; - completingDoubleAnimation.From = -ActualWidth; - } + if (Direction == TransitionDirection.Right) + { + startingDoubleAnimation.To = ActualWidth; + completingDoubleAnimation.From = -ActualWidth; + } - if (Direction == TransitionDirection.Left) - { - startingDoubleAnimation.To = -ActualWidth; - completingDoubleAnimation.From = ActualWidth; + if (Direction == TransitionDirection.Left) + { + startingDoubleAnimation.To = -ActualWidth; + completingDoubleAnimation.From = ActualWidth; + } } } diff --git a/src/ReactiveUI.XamForms/ActivationForViewFetcher.cs b/src/ReactiveUI.XamForms/ActivationForViewFetcher.cs index 06bb38be29..650a963417 100644 --- a/src/ReactiveUI.XamForms/ActivationForViewFetcher.cs +++ b/src/ReactiveUI.XamForms/ActivationForViewFetcher.cs @@ -40,7 +40,7 @@ public IObservable GetActivationForView(IActivatableView view) return activation.DistinctUntilChanged(); } - private static IObservable GetActivationFor(ICanActivate canActivate) + private static IObservable? GetActivationFor(ICanActivate? canActivate) { if (canActivate == null) { @@ -52,7 +52,7 @@ private static IObservable GetActivationFor(ICanActivate canActivate) canActivate.Deactivated.Select(_ => false)); } - private static IObservable GetActivationFor(Page page) + private static IObservable? GetActivationFor(Page? page) { if (page == null) { @@ -80,7 +80,7 @@ private static IObservable GetActivationFor(Page page) return Observable.Merge(appearing, disappearing); } - private static IObservable GetActivationFor(View view) + private static IObservable? GetActivationFor(View? view) { if (view == null) { @@ -102,7 +102,7 @@ private static IObservable GetActivationFor(View view) .StartWith(view.IsVisible); } - private static IObservable GetActivationFor(Cell cell) + private static IObservable? GetActivationFor(Cell? cell) { if (cell == null) { diff --git a/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs b/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs index 900479d87b..eb37899cbd 100644 --- a/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveCarouselPage.cs @@ -32,17 +32,17 @@ public class ReactiveCarouselPage : CarouselPage, IViewFor /// Gets or sets the ViewModel to display. /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveContentPage.cs b/src/ReactiveUI.XamForms/ReactiveContentPage.cs index 5a30182f8a..d27ba0e6f6 100644 --- a/src/ReactiveUI.XamForms/ReactiveContentPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveContentPage.cs @@ -32,17 +32,17 @@ public class ReactiveContentPage : ContentPage, IViewFor /// /// Gets or sets the ViewModel to display. /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveContentView.cs b/src/ReactiveUI.XamForms/ReactiveContentView.cs index 841d9202bf..9dedf73a68 100644 --- a/src/ReactiveUI.XamForms/ReactiveContentView.cs +++ b/src/ReactiveUI.XamForms/ReactiveContentView.cs @@ -32,17 +32,17 @@ public class ReactiveContentView : ContentView, IViewFor /// /// Gets or sets the ViewModel to display. /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveEntryCell.cs b/src/ReactiveUI.XamForms/ReactiveEntryCell.cs index aa67744662..1f6c8d75dc 100644 --- a/src/ReactiveUI.XamForms/ReactiveEntryCell.cs +++ b/src/ReactiveUI.XamForms/ReactiveEntryCell.cs @@ -29,17 +29,17 @@ public class ReactiveEntryCell : EntryCell, IViewFor propertyChanged: OnViewModelChanged); /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveImageCell.cs b/src/ReactiveUI.XamForms/ReactiveImageCell.cs index 4a92f090f4..a61d607912 100644 --- a/src/ReactiveUI.XamForms/ReactiveImageCell.cs +++ b/src/ReactiveUI.XamForms/ReactiveImageCell.cs @@ -29,17 +29,17 @@ public class ReactiveImageCell : ImageCell, IViewFor propertyChanged: OnViewModelChanged); /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs b/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs index 4704c03f91..1b699c1a04 100644 --- a/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveMasterDetailPage.cs @@ -32,17 +32,17 @@ public class ReactiveMasterDetailPage : MasterDetailPage, IViewFor /// Gets or sets the ViewModel to display. /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveMultiPage.cs b/src/ReactiveUI.XamForms/ReactiveMultiPage.cs index f424a7b3ef..4427aa4cab 100644 --- a/src/ReactiveUI.XamForms/ReactiveMultiPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveMultiPage.cs @@ -34,17 +34,17 @@ public abstract class ReactiveMultiPage : MultiPage, I /// /// Gets or sets the ViewModel to display. /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs b/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs index 11cac284a8..783f101212 100644 --- a/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveNavigationPage.cs @@ -32,17 +32,17 @@ public class ReactiveNavigationPage : NavigationPage, IViewFor /// Gets or sets the ViewModel to display. /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveSwitchCell.cs b/src/ReactiveUI.XamForms/ReactiveSwitchCell.cs index a9e66777b5..5213af8ceb 100644 --- a/src/ReactiveUI.XamForms/ReactiveSwitchCell.cs +++ b/src/ReactiveUI.XamForms/ReactiveSwitchCell.cs @@ -29,17 +29,17 @@ public class ReactiveSwitchCell : SwitchCell, IViewFor propertyChanged: OnViewModelChanged); /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs b/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs index 6f6196742a..17916e094d 100644 --- a/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs +++ b/src/ReactiveUI.XamForms/ReactiveTabbedPage.cs @@ -32,17 +32,17 @@ public class ReactiveTabbedPage : TabbedPage, IViewFor /// /// Gets or sets the ViewModel to display. /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveTextCell.cs b/src/ReactiveUI.XamForms/ReactiveTextCell.cs index a8980190b0..32edbb75cf 100644 --- a/src/ReactiveUI.XamForms/ReactiveTextCell.cs +++ b/src/ReactiveUI.XamForms/ReactiveTextCell.cs @@ -29,17 +29,17 @@ public class ReactiveTextCell : TextCell, IViewFor propertyChanged: OnViewModelChanged); /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/ReactiveUI.XamForms.csproj b/src/ReactiveUI.XamForms/ReactiveUI.XamForms.csproj index 775712e8f6..e8f76643ff 100644 --- a/src/ReactiveUI.XamForms/ReactiveUI.XamForms.csproj +++ b/src/ReactiveUI.XamForms/ReactiveUI.XamForms.csproj @@ -3,6 +3,7 @@ netstandard2.0 Contains the ReactiveUI platform specific extensions for Xamarin Forms ReactiveUI.XamForms + enable latest mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;xamarin;android;ios;mac;forms;monodroid;monotouch;xamarin.forms;net diff --git a/src/ReactiveUI.XamForms/ReactiveViewCell.cs b/src/ReactiveUI.XamForms/ReactiveViewCell.cs index b5ec6d774f..575362a0d1 100644 --- a/src/ReactiveUI.XamForms/ReactiveViewCell.cs +++ b/src/ReactiveUI.XamForms/ReactiveViewCell.cs @@ -29,17 +29,17 @@ public class ReactiveViewCell : ViewCell, IViewFor propertyChanged: OnViewModelChanged); /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } /// diff --git a/src/ReactiveUI.XamForms/RoutedViewHost.cs b/src/ReactiveUI.XamForms/RoutedViewHost.cs index dfe370c53b..71b7e9676c 100644 --- a/src/ReactiveUI.XamForms/RoutedViewHost.cs +++ b/src/ReactiveUI.XamForms/RoutedViewHost.cs @@ -45,7 +45,7 @@ public RoutedViewHost() bool popToRootPending = false; bool userInstigated = false; - this.WhenAnyObservable(x => x.Router.NavigationChanged) + this.WhenAnyObservable(x => x.Router.NavigationChanged!) .Where(_ => Router.NavigationStack.Count == 0) .Select(x => { @@ -58,7 +58,8 @@ public RoutedViewHost() .Subscribe() .DisposeWith(disposable); - Router.NavigationChanged + Router? + .NavigationChanged? .CountChanged() .Select(_ => Router.NavigationStack.Count) .StartWith(Router.NavigationStack.Count) @@ -111,7 +112,7 @@ public RoutedViewHost() .Subscribe() .DisposeWith(disposable); - Router + Router? .Navigate .SelectMany(_ => PageForViewModel(Router.GetCurrentViewModel())) .SelectMany(async page => @@ -158,14 +159,14 @@ public RoutedViewHost() try { - Router.NavigationStack.RemoveAt(Router.NavigationStack.Count - 1); + Router?.NavigationStack.RemoveAt(Router.NavigationStack.Count - 1); } finally { userInstigated = false; } - var vm = Router.GetCurrentViewModel(); + var vm = Router?.GetCurrentViewModel(); if (CurrentPage is IViewFor page && vm != null) { // don't replace view model if vm is null @@ -188,7 +189,7 @@ public RoutedViewHost() { return router.NavigationStack .ToObservable() - .Select(x => (Page)ViewLocator.Current.ResolveView(x)) + .Select(x => (Page)ViewLocator.Current.ResolveView(x) !) .SelectMany(x => PushAsync(x).ToObservable()) .Finally(() => { diff --git a/src/ReactiveUI.XamForms/ViewModelViewHost.cs b/src/ReactiveUI.XamForms/ViewModelViewHost.cs index 7bb7ccf88f..5b6cf5bfdb 100644 --- a/src/ReactiveUI.XamForms/ViewModelViewHost.cs +++ b/src/ReactiveUI.XamForms/ViewModelViewHost.cs @@ -47,7 +47,7 @@ public class ViewModelViewHost : ContentView, IViewFor Observable.Never, BindingMode.OneWay); - private string _viewContract; + private string? _viewContract; /// /// Initializes a new instance of the class. @@ -107,7 +107,7 @@ public ViewModelViewHost() /// /// Gets or sets the view model whose associated view is to be displayed. /// - public object ViewModel + public object? ViewModel { get => GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); @@ -125,7 +125,7 @@ public View DefaultContent /// /// Gets or sets the observable which signals when the contract to use when resolving the view for the given view model has changed. /// - public IObservable ViewContractObservable + public IObservable ViewContractObservable { get => (IObservable)GetValue(ViewContractObservableProperty); set => SetValue(ViewContractObservableProperty, value); @@ -137,7 +137,7 @@ public IObservable ViewContractObservable /// /// This property is a mere convenience so that a fixed contract can be assigned directly in XAML. /// - public string ViewContract + public string? ViewContract { get => _viewContract; set => ViewContractObservable = Observable.Return(value); @@ -146,6 +146,6 @@ public string ViewContract /// /// Gets or sets the override for the view locator to use when resolving the view. If unspecified, will be used. /// - public IViewLocator ViewLocator { get; set; } + public IViewLocator? ViewLocator { get; set; } } } diff --git a/src/ReactiveUI/Activation/ViewForMixins.cs b/src/ReactiveUI/Activation/ViewForMixins.cs index 88a0fe7ed7..330dc3ef3e 100644 --- a/src/ReactiveUI/Activation/ViewForMixins.cs +++ b/src/ReactiveUI/Activation/ViewForMixins.cs @@ -18,14 +18,14 @@ namespace ReactiveUI /// public static class ViewForMixins { - private static readonly MemoizingMRUCache activationFetcherCache = - new MemoizingMRUCache( + private static readonly MemoizingMRUCache activationFetcherCache = + new MemoizingMRUCache( (t, _) => Locator.Current - .GetServices() - .Aggregate((count: 0, viewFetcher: default(IActivationForViewFetcher)), (acc, x) => + .GetServices() + .Aggregate((count: 0, viewFetcher: default(IActivationForViewFetcher?)), (acc, x) => { - int score = x.GetAffinityForView(t); + int score = x?.GetAffinityForView(t) ?? 0; return score > acc.count ? (score, x) : acc; }).viewFetcher, RxApp.SmallCacheLimit); @@ -142,7 +142,7 @@ public static IDisposable WhenActivated(this IActivatableView item, Func /// A Disposable that deactivates this registration. - public static IDisposable WhenActivated(this IActivatableView item, Func> block, IViewFor view) + public static IDisposable WhenActivated(this IActivatableView item, Func> block, IViewFor? view) { if (item == null) { @@ -182,7 +182,7 @@ public static IDisposable WhenActivated(this IActivatableView item, FuncA Disposable that deactivates this registration. public static IDisposable WhenActivated(this IActivatableView item, Action> block) { - return item.WhenActivated(block, null); + return item.WhenActivated(block, null!); } /// @@ -229,7 +229,7 @@ public static IDisposable WhenActivated(this IActivatableView item, Action /// A Disposable that deactivates this registration. - public static IDisposable WhenActivated(this IActivatableView item, Action block, IViewFor view = null) + public static IDisposable WhenActivated(this IActivatableView item, Action block, IViewFor? view = null) { return item.WhenActivated( () => diff --git a/src/ReactiveUI/Bindings/Command/CommandBinder.cs b/src/ReactiveUI/Bindings/Command/CommandBinder.cs index cbc31b1ba3..93a6e18fe7 100644 --- a/src/ReactiveUI/Bindings/Command/CommandBinder.cs +++ b/src/ReactiveUI/Bindings/Command/CommandBinder.cs @@ -56,7 +56,7 @@ public static IReactiveBinding BindCommand> propertyName, Expression> controlName, IObservable withParameter, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand @@ -87,7 +87,7 @@ public static IReactiveBinding BindCommand> propertyName, Expression> controlName, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand @@ -122,7 +122,7 @@ public static IReactiveBinding BindCommand> propertyName, Expression> controlName, Expression> withParameter, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand diff --git a/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs b/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs index 4afdc57785..d457b8383e 100644 --- a/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs +++ b/src/ReactiveUI/Bindings/Command/CommandBinderImplementation.cs @@ -46,7 +46,7 @@ public IReactiveBinding BindCommand> vmProperty, Expression> controlProperty, Func withParameter, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand @@ -65,7 +65,7 @@ public IReactiveBinding BindCommand(); - IDisposable bindingDisposable = BindCommandInternal(source, view, controlExpression, Observable.Defer(() => Observable.Return(withParameter())), toEvent, cmd => + IDisposable bindingDisposable = BindCommandInternal(source, view, controlExpression, Observable.Defer(() => Observable.Return(withParameter())), toEvent ?? string.Empty, cmd => { var rc = cmd as IReactiveCommand; if (rc == null) @@ -113,7 +113,7 @@ public IReactiveBinding BindCommand> vmProperty, Expression> controlProperty, IObservable withParameter, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand @@ -144,13 +144,13 @@ public IReactiveBinding BindCommand( + private static IDisposable BindCommandInternal( IObservable @this, TView view, Expression controlExpression, IObservable withParameter, - string toEvent, - Func commandFixuper = null) + string? toEvent, + Func? commandFixuper = null) where TView : class, IViewFor where TProp : ICommand { @@ -175,11 +175,11 @@ private IDisposable BindCommandInternal( var cmd = commandFixuper != null ? commandFixuper(x.val) : x.val; if (toEvent != null) { - disp = CreatesCommandBinding.BindCommandToObject(cmd, x.host, withParameter.Select(y => (object)y), toEvent); + disp = CreatesCommandBinding.BindCommandToObject(cmd, x.host, withParameter.Select(y => (object)y!), toEvent); } else { - disp = CreatesCommandBinding.BindCommandToObject(cmd, x.host, withParameter.Select(y => (object)y)); + disp = CreatesCommandBinding.BindCommandToObject(cmd, x.host, withParameter.Select(y => (object)y!)); } }); diff --git a/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs b/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs index 8e6a7743d0..5101276526 100644 --- a/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs +++ b/src/ReactiveUI/Bindings/Command/CommandBinderImplementationMixins.cs @@ -25,7 +25,7 @@ public static IReactiveBinding BindCommand> propertyName, Expression> controlName, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand @@ -40,7 +40,7 @@ public static IReactiveBinding BindCommand> propertyName, Expression> controlName, Expression> withParameter, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs index a28ef67981..619aaa328d 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBinding.cs @@ -16,24 +16,24 @@ namespace ReactiveUI { internal class CreatesCommandBinding { - private static readonly MemoizingMRUCache bindCommandCache = - new MemoizingMRUCache( + private static readonly MemoizingMRUCache bindCommandCache = + new MemoizingMRUCache( (t, _) => { return Locator.Current.GetServices() - .Aggregate((score: 0, binding: (ICreatesCommandBinding)null), (acc, x) => + .Aggregate((score: 0, binding: (ICreatesCommandBinding?)null), (acc, x) => { int score = x.GetAffinityForObject(t, false); return (score > acc.score) ? (score, x) : acc; }).binding; }, RxApp.SmallCacheLimit); - private static readonly MemoizingMRUCache bindCommandEventCache = - new MemoizingMRUCache( + private static readonly MemoizingMRUCache bindCommandEventCache = + new MemoizingMRUCache( (t, _) => { return Locator.Current.GetServices() - .Aggregate((score: 0, binding: (ICreatesCommandBinding)null), (acc, x) => + .Aggregate((score: 0, binding: (ICreatesCommandBinding?)null), (acc, x) => { int score = x.GetAffinityForObject(t, true); return (score > acc.score) ? (score, x) : acc; @@ -73,7 +73,7 @@ public static IDisposable BindCommandToObject(ICommand command, object target, I var mi = binder.GetType().GetTypeInfo().DeclaredMethods.First(x => x.Name == "BindCommandToObject" && x.IsGenericMethod); mi = mi.MakeGenericMethod(new[] { eventArgsType }); - var ret = (IDisposable)mi.Invoke(binder, new[] { command, target, commandParameter, eventName }); + var ret = (IDisposable)mi.Invoke(binder, new[] { command, target, commandParameter, eventName }) !; if (ret == null) { throw new Exception($"Couldn't bind Command Binder for {type.FullName} and event {eventName}"); diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs index 8986c71e9b..82e731436c 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaCommandParameter.cs @@ -38,7 +38,7 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// - public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter) + public IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter) { if (target == null) { @@ -50,23 +50,23 @@ public IDisposable BindCommandToObject(ICommand command, object target, IObserva var cmdParamPi = type.GetRuntimeProperty("CommandParameter"); var ret = new CompositeDisposable(); - var originalCmd = cmdPi.GetValue(target, null); - var originalCmdParam = cmdParamPi.GetValue(target, null); + var originalCmd = cmdPi?.GetValue(target, null); + var originalCmdParam = cmdParamPi?.GetValue(target, null); ret.Add(Disposable.Create(() => { - cmdPi.SetValue(target, originalCmd, null); - cmdParamPi.SetValue(target, originalCmdParam, null); + cmdPi?.SetValue(target, originalCmd, null); + cmdParamPi?.SetValue(target, originalCmdParam, null); })); - ret.Add(commandParameter.Subscribe(x => cmdParamPi.SetValue(target, x, null))); - cmdPi.SetValue(target, command, null); + ret.Add(commandParameter.Subscribe(x => cmdParamPi?.SetValue(target, x, null))); + cmdPi?.SetValue(target, command, null); return ret; } /// - public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) + public IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) #if MONO where TEventArgs : EventArgs #endif diff --git a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs index 1a2d5eb753..7ce9aeee80 100644 --- a/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs +++ b/src/ReactiveUI/Bindings/Command/CreatesCommandBindingViaEvent.cs @@ -49,7 +49,7 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// - public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter) + public IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter) { if (target == null) { @@ -70,7 +70,7 @@ public IDisposable BindCommandToObject(ICommand command, object target, IObserva var mi = GetType().GetRuntimeMethods().First(x => x.Name == "BindCommandToObject" && x.IsGenericMethod); mi = mi.MakeGenericMethod(eventInfo.Args); - return (IDisposable)mi.Invoke(this, new[] { command, target, commandParameter, eventInfo.EventInfo.Name }); + return (IDisposable?)mi.Invoke(this, new[] { command, target, commandParameter, eventInfo.EventInfo?.Name }); } /// @@ -81,7 +81,7 @@ public IDisposable BindCommandToObject(ICommand command, object targ { var ret = new CompositeDisposable(); - object latestParameter = null; + object? latestParameter = null; var evt = Observable.FromEventPattern(target, eventName); ret.Add(commandParameter.Subscribe(x => latestParameter = x)); diff --git a/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs b/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs index c3d8bd25f2..7bc7210381 100644 --- a/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs +++ b/src/ReactiveUI/Bindings/Command/ICommandBinderImplementation.cs @@ -40,7 +40,7 @@ IReactiveBinding BindCommand> propertyName, Expression> controlName, Func withParameter, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand; @@ -66,7 +66,7 @@ IReactiveBinding BindCommand> propertyName, Expression> controlName, IObservable withParameter, - string toEvent = null) + string? toEvent = null) where TViewModel : class where TView : class, IViewFor where TProp : ICommand; diff --git a/src/ReactiveUI/Bindings/Command/RelayCommand.cs b/src/ReactiveUI/Bindings/Command/RelayCommand.cs index bf629c0a1e..fc2c621992 100644 --- a/src/ReactiveUI/Bindings/Command/RelayCommand.cs +++ b/src/ReactiveUI/Bindings/Command/RelayCommand.cs @@ -23,13 +23,13 @@ internal class RelayCommand : ICommand private readonly Action _execute; private bool? _prevCanExecute; - public RelayCommand(Func canExecute = null, Action execute = null) + public RelayCommand(Func? canExecute = null, Action? execute = null) { _canExecute = canExecute ?? (_ => true); _execute = execute ?? (_ => { }); } - public event EventHandler CanExecuteChanged; + public event EventHandler? CanExecuteChanged; public bool CanExecute(object parameter) { diff --git a/src/ReactiveUI/Bindings/Converter/EqualityTypeConverter.cs b/src/ReactiveUI/Bindings/Converter/EqualityTypeConverter.cs index 93aee64aff..206f2ac030 100644 --- a/src/ReactiveUI/Bindings/Converter/EqualityTypeConverter.cs +++ b/src/ReactiveUI/Bindings/Converter/EqualityTypeConverter.cs @@ -20,10 +20,10 @@ public class EqualityTypeConverter : IBindingTypeConverter private static readonly MemoizingMRUCache _referenceCastCache = new MemoizingMRUCache( (t, _) => { - return _methodInfo = _methodInfo ?? typeof(EqualityTypeConverter).GetRuntimeMethods().First(x => x.Name == nameof(DoReferenceCast)); + return _methodInfo ??= typeof(EqualityTypeConverter).GetRuntimeMethods().First(x => x.Name == nameof(DoReferenceCast)); }, RxApp.SmallCacheLimit); - private static MethodInfo _methodInfo; + private static MethodInfo? _methodInfo; /// /// Handles casting for a reference. Understands about nullable types @@ -33,7 +33,7 @@ public class EqualityTypeConverter : IBindingTypeConverter /// The target we want to cast to. /// The new value after it has been casted. /// If we cannot cast the object. - public static object DoReferenceCast(object from, Type targetType) + public static object? DoReferenceCast(object? from, Type targetType) { var backingNullableType = Nullable.GetUnderlyingType(targetType); @@ -101,9 +101,12 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public bool TryConvert(object from, Type toType, object conversionHint, out object result) + public bool TryConvert(object? @from, Type toType, object? conversionHint, out object? result) { - Contract.Requires(toType != null); + if (toType == null) + { + throw new ArgumentNullException(nameof(toType)); + } var mi = _referenceCastCache.Get(toType); diff --git a/src/ReactiveUI/Bindings/Converter/StringConverter.cs b/src/ReactiveUI/Bindings/Converter/StringConverter.cs index f815c775d1..feb96a80d3 100644 --- a/src/ReactiveUI/Bindings/Converter/StringConverter.cs +++ b/src/ReactiveUI/Bindings/Converter/StringConverter.cs @@ -20,7 +20,7 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public bool TryConvert(object from, Type toType, object conversionHint, out object result) + public bool TryConvert(object? @from, Type toType, object? conversionHint, out object? result) { // XXX: All Of The Localization result = from?.ToString(); diff --git a/src/ReactiveUI/Bindings/IBindingTypeConverter.cs b/src/ReactiveUI/Bindings/IBindingTypeConverter.cs index c31f3a7abd..3da99d9c73 100644 --- a/src/ReactiveUI/Bindings/IBindingTypeConverter.cs +++ b/src/ReactiveUI/Bindings/IBindingTypeConverter.cs @@ -34,9 +34,9 @@ public interface IBindingTypeConverter : IEnableLogger /// The object to convert. /// The type to coerce the object to. /// An implementation-defined value, - /// usually to specify things like locale awareness. + /// usually to specify things like locale awareness. /// An object that is of the type . /// True if conversion was successful. - bool TryConvert(object from, Type toType, object conversionHint, out object result); + bool TryConvert(object? @from, Type toType, object? conversionHint, out object? result); } } diff --git a/src/ReactiveUI/Bindings/ISetMethodBindingConverter.cs b/src/ReactiveUI/Bindings/ISetMethodBindingConverter.cs index ee4ae79eb0..e83cd7d643 100644 --- a/src/ReactiveUI/Bindings/ISetMethodBindingConverter.cs +++ b/src/ReactiveUI/Bindings/ISetMethodBindingConverter.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Text; using Splat; @@ -35,6 +36,7 @@ public interface ISetMethodBindingConverter : IEnableLogger /// The value to set on the new object. /// The arguments required. Used for indexer based values. /// The value that was set. - object PerformSet(object toTarget, object newValue, object[] arguments); + [SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:ClosingSquareBracketsMustBeSpacedCorrectly", Justification = "Reviewed.")] + object PerformSet(object? toTarget, object? newValue, object[]? arguments); } } diff --git a/src/ReactiveUI/Bindings/Property/IPropertyBinderImplementation.cs b/src/ReactiveUI/Bindings/Property/IPropertyBinderImplementation.cs index 235954b0dd..826f56ef16 100644 --- a/src/ReactiveUI/Bindings/Property/IPropertyBinderImplementation.cs +++ b/src/ReactiveUI/Bindings/Property/IPropertyBinderImplementation.cs @@ -64,15 +64,15 @@ public interface IPropertyBinderImplementation : IEnableLogger /// An instance of that, when disposed, /// disconnects the binding. /// - IReactiveBinding Bind( + IReactiveBinding? Bind( TViewModel viewModel, TView view, Expression> vmProperty, Expression> viewProperty, - IObservable signalViewUpdate, - object conversionHint, - IBindingTypeConverter vmToViewConverterOverride = null, - IBindingTypeConverter viewToVMConverterOverride = null) + IObservable? signalViewUpdate, + object? conversionHint, + IBindingTypeConverter? vmToViewConverterOverride = null, + IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, IViewFor; @@ -121,12 +121,12 @@ public interface IPropertyBinderImplementation : IEnableLogger /// An instance of that, when disposed, /// disconnects the binding. /// - IReactiveBinding Bind( + IReactiveBinding? Bind( TViewModel viewModel, TView view, Expression> vmProperty, Expression> viewProperty, - IObservable signalViewUpdate, + IObservable? signalViewUpdate, Func vmToViewConverter, Func viewToVmConverter) where TViewModel : class @@ -171,13 +171,13 @@ public interface IPropertyBinderImplementation : IEnableLogger /// /// There is no registered converter from to . /// - IReactiveBinding OneWayBind( + IReactiveBinding? OneWayBind( TViewModel viewModel, TView view, Expression> vmProperty, Expression> viewProperty, - object conversionHint, - IBindingTypeConverter vmToViewConverterOverride = null) + object? conversionHint, + IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, IViewFor; @@ -193,31 +193,31 @@ IReactiveBinding OneWayBindThe instance of the view model to bind to. /// The instance of the view to bind to. /// - /// An expression representing the property to be bound to on the view model. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always get the last value of the property chain. + /// An expression representing the property to be bound to on the view model. + /// This can be a child property, for example x => x.Foo.Bar.Baz in which case + /// the binding will attempt to subscribe recursively to updates in order to + /// always get the last value of the property chain. /// /// - /// An expression representing the property to be bound to on the view. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always set the correct property. + /// An expression representing the property to be bound to on the view. + /// This can be a child property, for example x => x.Foo.Bar.Baz in which case + /// the binding will attempt to subscribe recursively to updates in order to + /// always set the correct property. /// /// - /// A function that will be used to transform the values of the property on the view model - /// before being bound to the view property. + /// A function that will be used to transform the values of the property on the view model + /// before being bound to the view property. /// /// /// An instance of that, when disposed, /// disconnects the binding. /// - IReactiveBinding OneWayBind( - TViewModel viewModel, - TView view, - Expression> vmProperty, - Expression> viewProperty, - Func selector) + IReactiveBinding? OneWayBind( + TViewModel viewModel, + TView view, + Expression> vmProperty, + Expression> viewProperty, + Func selector) where TViewModel : class where TView : class, IViewFor; @@ -249,8 +249,8 @@ IDisposable BindTo( IObservable observedChange, TTarget target, Expression> propertyExpression, - object conversionHint, - IBindingTypeConverter vmToViewConverterOverride = null) + object? conversionHint, + IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class; } } diff --git a/src/ReactiveUI/Bindings/Property/PropertyBinderImplementation.cs b/src/ReactiveUI/Bindings/Property/PropertyBinderImplementation.cs index 4a5ac1e148..1d1a78d20b 100644 --- a/src/ReactiveUI/Bindings/Property/PropertyBinderImplementation.cs +++ b/src/ReactiveUI/Bindings/Property/PropertyBinderImplementation.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Linq.Expressions; @@ -18,20 +19,21 @@ namespace ReactiveUI /// /// Provides methods to bind properties to observables. /// + [SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "nullable object array.")] public class PropertyBinderImplementation : IPropertyBinderImplementation { - private static readonly MemoizingMRUCache<(Type fromType, Type toType), IBindingTypeConverter> _typeConverterCache = new MemoizingMRUCache<(Type fromType, Type toType), IBindingTypeConverter>( + private static readonly MemoizingMRUCache<(Type fromType, Type toType), IBindingTypeConverter?> _typeConverterCache = new MemoizingMRUCache<(Type fromType, Type toType), IBindingTypeConverter?>( (types, _) => { - return Locator.Current.GetServices() + return Locator.Current.GetServices() .Aggregate((currentAffinity: -1, currentBinding: default(IBindingTypeConverter)), (acc, x) => { - var score = x.GetAffinityForObjects(types.fromType, types.toType); + var score = x?.GetAffinityForObjects(types.fromType, types.toType) ?? -1; return score > acc.currentAffinity && score > 0 ? (score, x) : acc; }).currentBinding; }, RxApp.SmallCacheLimit); - private static readonly MemoizingMRUCache<(Type fromType, Type toType), ISetMethodBindingConverter> _setMethodCache = new MemoizingMRUCache<(Type fromType, Type toType), ISetMethodBindingConverter>( + private static readonly MemoizingMRUCache<(Type fromType, Type toType), ISetMethodBindingConverter?> _setMethodCache = new MemoizingMRUCache<(Type fromType, Type toType), ISetMethodBindingConverter?>( (type, _) => { return Locator.Current.GetServices() @@ -44,68 +46,16 @@ public class PropertyBinderImplementation : IPropertyBinderImplementation private delegate bool OutFunc(T1 t1, out T2 t2); - /// - /// Creates a two-way binding between a view model and a view. - /// This binding will attempt to convert the values of the - /// view and view model properties using a - /// if they are not of the same type. - /// - /// The type of the view model that is bound. - /// The type of the view being bound. - /// The type of the property bound on the view model. - /// The type of the property bound on the view. - /// - /// A dummy type, only the fact that - /// emits values is considered, not the actual values emitted. - /// - /// The instance of the view model object to be bound. - /// The instance of the view object to be bound. - /// - /// An expression representing the property to be bound to on the view model. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always get and set the correct property. - /// - /// - /// An expression representing the property to be bound to on the view. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always get and set the correct property. - /// - /// If it is left null, the framework will attempt to automatically figure out - /// the control and property that is to be bound, by looking for a control of the - /// same name as the , and its most natural property. - /// - /// - /// An observable, that when signaled, indicates that the view property - /// has been changed, and that the binding should update the view model - /// property accordingly. - /// - /// - /// An object that can provide a hint for the converter. - /// The semantics of this object is defined by the converter used. - /// - /// - /// An optional to use when converting from the - /// viewModel to view property. - /// - /// - /// An optional to use when converting from the - /// view to viewModel property. - /// - /// - /// An instance of that, when disposed, - /// disconnects the binding. - /// - public IReactiveBinding Bind( + /// + public IReactiveBinding Bind( TViewModel viewModel, TView view, Expression> vmProperty, Expression> viewProperty, - IObservable signalViewUpdate, - object conversionHint, - IBindingTypeConverter vmToViewConverterOverride = null, - IBindingTypeConverter viewToVMConverterOverride = null) + IObservable? signalViewUpdate, + object? conversionHint, + IBindingTypeConverter? vmToViewConverterOverride = null, + IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, IViewFor { @@ -118,71 +68,34 @@ public class PropertyBinderImplementation : IPropertyBinderImplementation $"Can't two-way convert between {typeof(TVMProp)} and {typeof(TVProp)}. To fix this, register a IBindingTypeConverter or call the version with the converter Func."); } +#pragma warning disable CS8601 // Possible null reference assignment. bool VmToViewFunc(TVMProp vmValue, out TVProp vValue) { - var result = vmToViewConverter.TryConvert(vmValue, typeof(TVProp), conversionHint, out object tmp); + var result = vmToViewConverter.TryConvert(vmValue, typeof(TVProp), conversionHint, out object? tmp); - vValue = result ? (TVProp)tmp : default(TVProp); + vValue = result ? (TVProp)tmp : default; return result; } bool ViewToVmFunc(TVProp vValue, out TVMProp vmValue) { - var result = viewToVMConverter.TryConvert(vValue, typeof(TVMProp), conversionHint, out object tmp); + var result = viewToVMConverter.TryConvert(vValue, typeof(TVMProp), conversionHint, out object? tmp); - vmValue = result ? (TVMProp)tmp : default(TVMProp); + vmValue = result ? (TVMProp)tmp : default; return result; } +#pragma warning restore CS8601 // Possible null reference assignment. return BindImpl(viewModel, view, vmProperty, viewProperty, signalViewUpdate, VmToViewFunc, ViewToVmFunc); } - /// - /// Binds the specified view model property to the given view property. - /// - /// The type of the view model being bound. - /// The type of the view being bound. - /// The type of the property bound on the view model. - /// The type of the property bound on the view. - /// - /// A dummy type, only the fact that - /// emits values is considered, not the actual values emitted. - /// - /// The instance of the view model to bind. - /// The instance of the view to bind. - /// - /// An expression indicating the property that is bound on the view model. - /// This can be a chain of properties of the form vm => vm.Foo.Bar.Baz - /// and the binder will attempt to subscribe to changes on each recursively. - /// - /// - /// The property on the view that is to be bound. - /// This can be a chain of properties of the form. view => view.Foo.Bar.Baz - /// and the binder will attempt to set the last one each time the view model property is updated. - /// - /// - /// An observable, that when signaled, indicates that the view property - /// has been changed, and that the binding should update the view model - /// property accordingly. - /// - /// - /// Delegate to convert the value of the view model's property's type to a value of the - /// view's property's type. - /// - /// - /// Delegate to convert the value of the view's property's type to a value of the - /// view model's property's type. - /// - /// - /// An instance of that, when disposed, - /// disconnects the binding. - /// - public IReactiveBinding Bind( + /// + public IReactiveBinding? Bind( TViewModel viewModel, TView view, Expression> vmProperty, Expression> viewProperty, - IObservable signalViewUpdate, + IObservable? signalViewUpdate, Func vmToViewConverter, Func viewToVmConverter) where TViewModel : class @@ -223,56 +136,14 @@ bool ViewToVmFunc(TVProp vValue, out TVMProp vmValue) return BindImpl(viewModel, view, vmProperty, viewProperty, signalViewUpdate, VmToViewFunc, ViewToVmFunc); } - /// - /// Creates a one-way binding, i.e. a binding that flows from the - /// to the only. This binding will - /// attempt to convert the value of the view model property to the view property if they - /// are not of the same type. - /// - /// The type of the view model that is bound. - /// The type of the view that is bound. - /// The type of the property bound on the view model. - /// The type of the property bound on the view. - /// The instance of the view model to bind to. - /// The instance of the view to bind to. - /// - /// An expression representing the property to be bound to on the view model. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always get the last value of the property chain. - /// - /// - /// An expression representing the property to be bound to on the view. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always set the correct property. - /// - /// If it is left null, the framework will attempt to automatically figure out - /// the control and property that is to be bound, by looking for a control of the - /// same name as the , and its most natural property. - /// - /// - /// An object that can provide a hint for the converter. - /// The semantics of this object is defined by the converter used. - /// - /// - /// Delegate to convert the value of the view model's property's type to a value of the - /// view's property's type. - /// - /// - /// An instance of that, when disposed, - /// disconnects the binding. - /// - /// - /// There is no registered converter from to . - /// - public IReactiveBinding OneWayBind( + /// + public IReactiveBinding? OneWayBind( TViewModel viewModel, TView view, Expression> vmProperty, Expression> viewProperty, - object conversionHint = null, - IBindingTypeConverter vmToViewConverterOverride = null) + object? conversionHint = null, + IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, IViewFor { @@ -305,7 +176,7 @@ public IReactiveBinding OneWayBind { - if (!converter.TryConvert(x, viewType, conversionHint, out object tmp)) + if (!converter.TryConvert(x, viewType, conversionHint, out object? tmp)) { return Observable.Empty; } @@ -313,52 +184,18 @@ public IReactiveBinding OneWayBind(source, view, viewExpression); + var (disposable, obs) = BindToDirect(source, view, viewExpression); return new ReactiveBinding(view, viewModel, viewExpression, vmExpression, obs, BindingDirection.OneWay, disposable); } - /// - /// Creates a one way binding with a selector, i.e. a binding that flows from the - /// to the only, and where the value of the view model - /// property is mapped through the before being set to the view. - /// - /// The type of the view model that is bound. - /// The type of the view that is bound. - /// The type of the property bound on the view model. - /// The return type of the . - /// The instance of the view model to bind to. - /// The instance of the view to bind to. - /// - /// An expression representing the property to be bound to on the view model. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always get the last value of the property chain. - /// - /// - /// An expression representing the property to be bound to on the view. - /// This can be a child property, for example x => x.Foo.Bar.Baz in which case - /// the binding will attempt to subscribe recursively to updates in order to - /// always set the correct property. - /// - /// If it is left null, the framework will attempt to automatically figure out - /// the control and property that is to be bound, by looking for a control of the - /// same name as the , and its most natural property. - /// - /// - /// A function that will be used to transform the values of the property on the view model - /// before being bound to the view property. - /// - /// - /// An instance of that, when disposed, - /// disconnects the binding. - /// - public IReactiveBinding OneWayBind( - TViewModel viewModel, - TView view, - Expression> vmProperty, - Expression> viewProperty, - Func selector) + /// + public IReactiveBinding? OneWayBind( + TViewModel viewModel, + TView view, + Expression> vmProperty, + Expression> viewProperty, + Func selector) where TViewModel : class where TView : class, IViewFor { @@ -380,43 +217,20 @@ public IReactiveBinding OneWayBind (TProp)x).Select(selector); + IObservable source = (IObservable)Reflection.ViewModelWhenAnyValue(viewModel, view, vmExpression).Select(x => (TProp)x).Select(selector); - var viewType = viewExpression.Type; var (disposable, obs) = BindToDirect(source, view, viewExpression); return new ReactiveBinding(view, viewModel, viewExpression, vmExpression, obs, BindingDirection.OneWay, disposable); } - /// - /// BindTo takes an Observable stream and applies it to a target - /// property. Conceptually it is similar to Subscribe(x => - /// target.property = x), but allows you to use child properties - /// without the null checks. - /// - /// The source type. - /// The target object type. - /// The type of the property on the target object. - /// The observable to apply to the target property. - /// The target object whose property will be set. - /// - /// An expression representing the target property to set. - /// This can be a child property (i.e. x.Foo.Bar.Baz). - /// - /// An object that can provide a hint for the converter. - /// The semantics of this object is defined by the converter used. - /// - /// - /// Delegate to convert the value of the view model's property's type to a value of the - /// view's property's type. - /// - /// An object that when disposed, disconnects the binding. + /// public IDisposable BindTo( IObservable observedChange, TTarget target, Expression> propertyExpression, - object conversionHint = null, - IBindingTypeConverter vmToViewConverterOverride = null) + object? conversionHint = null, + IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class { if (target == null) @@ -431,7 +245,7 @@ public IDisposable BindTo( var viewExpression = Reflection.Rewrite(propertyExpression.Body); - var ret = EvalBindingHooks(observedChange, target, null, viewExpression, BindingDirection.OneWay); + var ret = EvalBindingHooks(observedChange, target, null!, viewExpression, BindingDirection.OneWay); if (!ret) { return Disposable.Empty; @@ -459,12 +273,12 @@ public IDisposable BindTo( return disposable; } - internal static IBindingTypeConverter GetConverterForTypes(Type lhs, Type rhs) + internal static IBindingTypeConverter? GetConverterForTypes(Type lhs, Type rhs) { return _typeConverterCache.Get((lhs, rhs)); } - private static Func GetSetConverter(Type fromType, Type targetType) + private static Func? GetSetConverter(Type? fromType, Type targetType) { if (fromType == null) { @@ -482,20 +296,26 @@ private static Func GetSetConverter(Type fromT } private (IDisposable disposable, IObservable value) BindToDirect( - IObservable changeObservable, - TTarget target, - Expression viewExpression) + IObservable changeObservable, + TTarget target, + Expression viewExpression) where TTarget : class { var defaultSetter = Reflection.GetValueSetterOrThrow(viewExpression.GetMemberInfo()); var defaultGetter = Reflection.GetValueFetcherOrThrow(viewExpression.GetMemberInfo()); - object SetThenGet(object paramTarget, object paramValue, object[] paramParams) + + object? SetThenGet(object paramTarget, object? paramValue, object[]? paramParams) { - Func converter = GetSetConverter(paramValue?.GetType(), viewExpression.Type); + Func? converter = GetSetConverter(paramValue?.GetType(), viewExpression.Type); + + if (defaultGetter == null) + { + throw new InvalidOperationException($"{nameof(defaultGetter)} was not found."); + } if (converter == null) { - defaultSetter(paramTarget, paramValue, paramParams); + defaultSetter?.Invoke(paramTarget, paramValue ?? throw new ArgumentNullException(nameof(paramValue)), paramParams); return defaultGetter(paramTarget, paramParams); } @@ -507,7 +327,7 @@ object SetThenGet(object paramTarget, object paramValue, object[] paramParams) if (viewExpression.GetParent().NodeType == ExpressionType.Parameter) { - setObservable = changeObservable.Select(x => (TValue)SetThenGet(target, x, viewExpression.GetArgumentsArray())); + setObservable = changeObservable.Select(x => (TValue)SetThenGet(target, x, viewExpression.GetArgumentsArray()) !); } else { @@ -515,7 +335,19 @@ object SetThenGet(object paramTarget, object paramValue, object[] paramParams) setObservable = bindInfo .Where(x => x.host != null) - .Select(x => (TValue)SetThenGet(x.host, x.val, viewExpression.GetArgumentsArray())); + .Select(x => + { + var value = SetThenGet(x.host, x.val, viewExpression.GetArgumentsArray()); + + if (value == null) + { +#pragma warning disable CS8603 // Possible null reference return. + return default; +#pragma warning restore CS8603 // Possible null reference return. + } + + return (TValue)value; + }); } return (setObservable.Subscribe(_ => { }, ex => this.Log().Error(ex, $"{viewExpression} Binding received an Exception!")), setObservable); @@ -526,7 +358,12 @@ private bool EvalBindingHooks(TViewModel viewModel, TView vie { var hooks = Locator.Current.GetServices(); - Func[]> vmFetcher; + if (view == null) + { + throw new ArgumentNullException(nameof(view)); + } + + Func[]> vmFetcher; if (vmExpression != null) { vmFetcher = () => @@ -537,20 +374,20 @@ private bool EvalBindingHooks(TViewModel viewModel, TView vie } else { - vmFetcher = () => new IObservedChange[] + vmFetcher = () => new IObservedChange[] { - new ObservedChange(null, null, viewModel) + new ObservedChange(null!, null!, viewModel) }; } - var vFetcher = new Func[]>(() => + var vFetcher = new Func[]>(() => { Reflection.TryGetAllValuesForPropertyChain(out var fetchedValues, view, viewExpression.GetExpressionChain()); return fetchedValues; }); var shouldBind = hooks.Aggregate(true, (acc, x) => - acc && x.ExecuteHook(viewModel, view, vmFetcher, vFetcher, direction)); + acc && x.ExecuteHook(viewModel, view, vmFetcher!, vFetcher!, direction)); if (!shouldBind) { @@ -562,12 +399,12 @@ private bool EvalBindingHooks(TViewModel viewModel, TView vie return shouldBind; } - private IReactiveBinding BindImpl( + private IReactiveBinding BindImpl( TViewModel viewModel, TView view, Expression> vmProperty, Expression> viewProperty, - IObservable signalViewUpdate, + IObservable? signalViewUpdate, OutFunc vmToViewConverter, OutFunc viewToVmConverter) where TView : class, IViewFor @@ -596,7 +433,7 @@ private bool EvalBindingHooks(TViewModel viewModel, TView vie signalInitialUpdate.Select(_ => true), signalObservable); - var changeWithValues = somethingChanged.Select(isVm => + var changeWithValues = somethingChanged.Select(isVm => { if (!Reflection.TryGetValueForPropertyChain(out TVMProp vmValue, view.ViewModel, vmExpression.GetExpressionChain()) || !Reflection.TryGetValueForPropertyChain(out TVProp vValue, view, viewExpression.GetExpressionChain())) @@ -611,7 +448,7 @@ private bool EvalBindingHooks(TViewModel viewModel, TView vie return (false, null, false); } - return (true, (object)vmAsView, isVm); + return (true, vmAsView, isVm); } if (!viewToVmConverter(vValue, out TVMProp vAsViewModel) || EqualityComparer.Default.Equals(vmValue, vAsViewModel)) @@ -619,19 +456,20 @@ private bool EvalBindingHooks(TViewModel viewModel, TView vie return (false, null, false); } - return (true, (object)vAsViewModel, isVm); + return (true, vAsViewModel, isVm); }); var ret = EvalBindingHooks(viewModel, view, vmExpression, viewExpression, BindingDirection.TwoWay); if (!ret) { - return null; + return null!; } - IObservable<(object view, bool isViewModel)> changes = changeWithValues + IObservable<(object? view, bool isViewModel)> changes = changeWithValues .Where(value => value.isValid) .Select(value => (value.view, value.isViewModel)) - .Publish().RefCount(); + .Publish() + .RefCount(); IDisposable disposable = changes.Subscribe(isVmWithLatestValue => { @@ -649,7 +487,7 @@ private bool EvalBindingHooks(TViewModel viewModel, TView vie // want the ViewModel to win at first. signalInitialUpdate.OnNext(true); - return new ReactiveBinding( + return new ReactiveBinding( view, viewModel, viewExpression, diff --git a/src/ReactiveUI/Bindings/Property/PropertyBindingMixins.cs b/src/ReactiveUI/Bindings/Property/PropertyBindingMixins.cs index 5a7585c019..2f1b7bcd58 100644 --- a/src/ReactiveUI/Bindings/Property/PropertyBindingMixins.cs +++ b/src/ReactiveUI/Bindings/Property/PropertyBindingMixins.cs @@ -57,23 +57,23 @@ static PropertyBindingMixins() /// An instance of that, when disposed, /// disconnects the binding. /// - public static IReactiveBinding Bind( + public static IReactiveBinding? Bind( this TView view, TViewModel viewModel, Expression> vmProperty, Expression> viewProperty, - object conversionHint = null, - IBindingTypeConverter vmToViewConverterOverride = null, - IBindingTypeConverter viewToVMConverterOverride = null) + object? conversionHint = null, + IBindingTypeConverter? vmToViewConverterOverride = null, + IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, IViewFor { - return binderImplementation.Bind( + return binderImplementation?.Bind( viewModel, view, vmProperty, viewProperty, - (IObservable)null, + (IObservable?)null, conversionHint, vmToViewConverterOverride, viewToVMConverterOverride); @@ -124,15 +124,15 @@ static PropertyBindingMixins() /// An instance of that, when disposed, /// disconnects the binding. /// - public static IReactiveBinding Bind( + public static IReactiveBinding? Bind( this TView view, TViewModel viewModel, Expression> vmProperty, Expression> viewProperty, - IObservable signalViewUpdate, - object conversionHint = null, - IBindingTypeConverter vmToViewConverterOverride = null, - IBindingTypeConverter viewToVMConverterOverride = null) + IObservable? signalViewUpdate, + object? conversionHint = null, + IBindingTypeConverter? vmToViewConverterOverride = null, + IBindingTypeConverter? viewToVMConverterOverride = null) where TViewModel : class where TView : class, IViewFor => binderImplementation.Bind(viewModel, view, vmProperty, viewProperty, signalViewUpdate, conversionHint, vmToViewConverterOverride, viewToVMConverterOverride); @@ -168,7 +168,7 @@ static PropertyBindingMixins() /// An instance of that, when disposed, /// disconnects the binding. /// - public static IReactiveBinding Bind( + public static IReactiveBinding? Bind( this TView view, TViewModel viewModel, Expression> vmProperty, @@ -176,7 +176,7 @@ static PropertyBindingMixins() Func vmToViewConverter, Func viewToVmConverter) where TViewModel : class - where TView : class, IViewFor => binderImplementation.Bind(viewModel, view, vmProperty, viewProperty, (IObservable)null, vmToViewConverter, viewToVmConverter); + where TView : class, IViewFor => binderImplementation.Bind(viewModel, view, vmProperty, viewProperty, (IObservable?)null, vmToViewConverter, viewToVmConverter); /// /// Binds the specified view model property to the given view property. @@ -218,12 +218,12 @@ static PropertyBindingMixins() /// An instance of that, when disposed, /// disconnects the binding. /// - public static IReactiveBinding Bind( + public static IReactiveBinding? Bind( this TView view, TViewModel viewModel, Expression> vmProperty, Expression> viewProperty, - IObservable signalViewUpdate, + IObservable? signalViewUpdate, Func vmToViewConverter, Func viewToVmConverter) where TViewModel : class @@ -268,13 +268,13 @@ static PropertyBindingMixins() /// An instance of that, when disposed, /// disconnects the binding. /// - public static IReactiveBinding OneWayBind( + public static IReactiveBinding? OneWayBind( this TView view, TViewModel viewModel, Expression> vmProperty, Expression> viewProperty, - object conversionHint = null, - IBindingTypeConverter vmToViewConverterOverride = null) + object? conversionHint = null, + IBindingTypeConverter? vmToViewConverterOverride = null) where TViewModel : class where TView : class, IViewFor { @@ -317,7 +317,7 @@ public static IReactiveBinding OneWayBind that, when disposed, /// disconnects the binding. /// - public static IReactiveBinding OneWayBind( + public static IReactiveBinding? OneWayBind( this TView view, TViewModel viewModel, Expression> vmProperty, @@ -357,8 +357,8 @@ public static IDisposable BindTo( this IObservable @this, TTarget target, Expression> property, - object conversionHint = null, - IBindingTypeConverter vmToViewConverterOverride = null) + object? conversionHint = null, + IBindingTypeConverter? vmToViewConverterOverride = null) where TTarget : class { return binderImplementation.BindTo(@this, target, property, conversionHint, vmToViewConverterOverride); diff --git a/src/ReactiveUI/Comparers/ChainedComparer.cs b/src/ReactiveUI/Comparers/ChainedComparer.cs index fc1579915e..48469fed8d 100644 --- a/src/ReactiveUI/Comparers/ChainedComparer.cs +++ b/src/ReactiveUI/Comparers/ChainedComparer.cs @@ -5,29 +5,32 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace ReactiveUI { internal sealed class ChainedComparer : IComparer { - private readonly IComparer _parent; + private readonly IComparer? _parent; private readonly Comparison _inner; - public ChainedComparer(IComparer parent, Comparison comparison) + public ChainedComparer(IComparer? parent, Comparison comparison) { - if (comparison == null) - { - throw new ArgumentNullException(nameof(comparison)); - } - _parent = parent; _inner = comparison; } /// +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). public int Compare(T x, T y) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). { - int parentResult = _parent == null ? 0 : _parent.Compare(x, y); + int parentResult = _parent?.Compare(x, y) ?? 0; + + if (x == null && y == null) + { + return 0; + } return parentResult != 0 ? parentResult : _inner(x, y); } diff --git a/src/ReactiveUI/Comparers/ComparerChainingExtensions.cs b/src/ReactiveUI/Comparers/ComparerChainingExtensions.cs index 8cd066b0b9..c6dd53987c 100644 --- a/src/ReactiveUI/Comparers/ComparerChainingExtensions.cs +++ b/src/ReactiveUI/Comparers/ComparerChainingExtensions.cs @@ -28,7 +28,7 @@ public static class ComparerChainingExtensions /// A function supplying the values for the comparer. /// /// A comparer. - public static IComparer ThenBy(this IComparer parent, Func selector) + public static IComparer ThenBy(this IComparer? parent, Func selector) { return ThenBy(parent, selector, Comparer.Default); } @@ -52,7 +52,7 @@ public static IComparer ThenBy(this IComparer parent, Func /// A comparer. - public static IComparer ThenBy(this IComparer parent, Func selector, IComparer comparer) + public static IComparer ThenBy(this IComparer? parent, Func selector, IComparer comparer) { return new ChainedComparer(parent, (x, y) => comparer.Compare(selector(x), selector(y))); } @@ -72,7 +72,7 @@ public static IComparer ThenBy(this IComparer parent, Func /// A comparer. - public static IComparer ThenByDescending(this IComparer parent, Func selector) + public static IComparer ThenByDescending(this IComparer? parent, Func selector) { return ThenByDescending(parent, selector, Comparer.Default); } @@ -96,7 +96,7 @@ public static IComparer ThenByDescending(this IComparer parent, /// The comparer to use when comparing the values returned by the selector. /// /// A comparer. - public static IComparer ThenByDescending(this IComparer parent, Func selector, IComparer comparer) + public static IComparer ThenByDescending(this IComparer? parent, Func selector, IComparer comparer) { return new ChainedComparer(parent, (x, y) => -comparer.Compare(selector(x), selector(y))); } diff --git a/src/ReactiveUI/Expression/Reflection.cs b/src/ReactiveUI/Expression/Reflection.cs index 08cd5d2ee4..7f5938e551 100644 --- a/src/ReactiveUI/Expression/Reflection.cs +++ b/src/ReactiveUI/Expression/Reflection.cs @@ -12,6 +12,7 @@ using System.Reactive.Linq; using System.Reflection; using System.Text; + using Splat; namespace ReactiveUI @@ -19,11 +20,12 @@ namespace ReactiveUI /// /// Helper class for handling Reflection amd Expression tree related items. /// + [SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "nullable object array.")] public static class Reflection { private static readonly ExpressionRewriter expressionRewriter = new ExpressionRewriter(); - private static readonly MemoizingMRUCache typeCache = new MemoizingMRUCache( + private static readonly MemoizingMRUCache _typeCache = new MemoizingMRUCache( (type, _) => { return Type.GetType( @@ -70,7 +72,10 @@ public static Expression Rewrite(Expression expression) /// A string form for the property the expression is pointing to. public static string ExpressionToPropertyNames(Expression expression) { - Contract.Requires(expression != null); + if (expression == null) + { + throw new ArgumentNullException(nameof(expression)); + } StringBuilder sb = new StringBuilder(); @@ -115,17 +120,17 @@ public static string ExpressionToPropertyNames(Expression expression) /// /// The member info to convert. /// A Func that takes in the object/indexes and returns the value. - public static Func GetValueFetcherForProperty(MemberInfo member) + public static Func? GetValueFetcherForProperty(MemberInfo member) { Contract.Requires(member != null); - FieldInfo field = member as FieldInfo; + FieldInfo? field = member as FieldInfo; if (field != null) { - return (obj, _) => field.GetValue(obj); + return (obj, _) => field.GetValue(obj) ?? throw new InvalidOperationException(); } - PropertyInfo property = member as PropertyInfo; + PropertyInfo? property = member as PropertyInfo; if (property != null) { return property.GetValue; @@ -142,7 +147,7 @@ public static Func GetValueFetcherForProperty(MemberIn /// /// The member info to convert. /// A Func that takes in the object/indexes and returns the value. - public static Func GetValueFetcherOrThrow(MemberInfo member) + public static Func GetValueFetcherOrThrow(MemberInfo member) { if (member is null) { @@ -167,23 +172,23 @@ public static Func GetValueFetcherOrThrow(MemberInfo m /// /// The member info to convert. /// A Func that takes in the object/indexes and sets the value. - public static Action GetValueSetterForProperty(MemberInfo member) + public static Action GetValueSetterForProperty(MemberInfo member) { Contract.Requires(member != null); - FieldInfo field = member as FieldInfo; + FieldInfo? field = member as FieldInfo; if (field != null) { return (obj, val, _) => field.SetValue(obj, val); } - PropertyInfo property = member as PropertyInfo; + PropertyInfo? property = member as PropertyInfo; if (property != null) { return property.SetValue; } - return null; + return null!; } /// @@ -194,7 +199,7 @@ public static Action GetValueSetterForProperty(MemberI /// /// The member info to convert. /// A Func that takes in the object/indexes and sets the value. - public static Action GetValueSetterOrThrow(MemberInfo member) + public static Action? GetValueSetterOrThrow(MemberInfo member) { if (member is null) { @@ -222,14 +227,14 @@ public static Action GetValueSetterOrThrow(MemberInfo /// A list of expressions which will point towards a property or field. /// The type of the end value we are trying to get. /// If the value was successfully retrieved or not. - public static bool TryGetValueForPropertyChain(out TValue changeValue, object current, IEnumerable expressionChain) + public static bool TryGetValueForPropertyChain(out TValue changeValue, object? current, IEnumerable expressionChain) { var expressions = expressionChain.ToList(); foreach (Expression expression in expressions.SkipLast(1)) { if (current == null) { - changeValue = default(TValue); + changeValue = default!; return false; } @@ -238,12 +243,14 @@ public static bool TryGetValueForPropertyChain(out TValue changeValue, o if (current == null) { - changeValue = default(TValue); + changeValue = default!; return false; } Expression lastExpression = expressions.Last(); +#pragma warning disable CS8601 // Possible null reference assignment. changeValue = (TValue)GetValueFetcherOrThrow(lastExpression.GetMemberInfo())(current, lastExpression.GetArgumentsArray()); +#pragma warning restore CS8601 // Possible null reference assignment. return true; } @@ -258,7 +265,7 @@ public static bool TryGetValueForPropertyChain(out TValue changeValue, o /// The object that starts the property chain. /// A list of expressions which will point towards a property or field. /// If the value was successfully retrieved or not. - public static bool TryGetAllValuesForPropertyChain(out IObservedChange[] changeValues, object current, IEnumerable expressionChain) + public static bool TryGetAllValuesForPropertyChain(out IObservedChange[] changeValues, object? current, IEnumerable expressionChain) { int currentIndex = 0; var expressions = expressionChain.ToList(); @@ -268,24 +275,28 @@ public static bool TryGetAllValuesForPropertyChain(out IObservedChange(sender, expression, current); +#pragma warning restore CS8604 // Possible null reference argument. currentIndex++; } if (current == null) { - changeValues[currentIndex] = null; + changeValues[currentIndex] = null!; return false; } Expression lastExpression = expressions.Last(); +#pragma warning disable CS8604 // Possible null reference argument. changeValues[currentIndex] = new ObservedChange(current, lastExpression, GetValueFetcherOrThrow(lastExpression.GetMemberInfo())(current, lastExpression.GetArgumentsArray())); +#pragma warning restore CS8604 // Possible null reference argument. return true; } @@ -303,7 +314,7 @@ public static bool TryGetAllValuesForPropertyChain(out IObservedChangeIf we should throw if we are unable to set the value. /// The type of the end value we are trying to set. /// If the value was successfully retrieved or not. - public static bool TrySetValueToPropertyChain(object target, IEnumerable expressionChain, TValue value, bool shouldThrow = true) + public static bool TrySetValueToPropertyChain(object? target, IEnumerable expressionChain, TValue value, bool shouldThrow = true) { var expressions = expressionChain.ToList(); foreach (Expression expression in expressions.SkipLast(1)) @@ -312,7 +323,10 @@ public static bool TrySetValueToPropertyChain(object target, IEnumerable GetValueFetcherOrThrow(expression.GetMemberInfo()) : GetValueFetcherForProperty(expression.GetMemberInfo()); - target = getter(target, expression.GetArgumentsArray()); + if (getter != null) + { + target = getter(target ?? throw new ArgumentNullException(nameof(target)), expression.GetArgumentsArray()); + } } if (target == null) @@ -321,7 +335,7 @@ public static bool TrySetValueToPropertyChain(object target, IEnumerable } Expression lastExpression = expressions.Last(); - Action setter = shouldThrow ? + Action? setter = shouldThrow ? GetValueSetterOrThrow(lastExpression.GetMemberInfo()) : GetValueSetterForProperty(lastExpression.GetMemberInfo()); @@ -342,9 +356,9 @@ public static bool TrySetValueToPropertyChain(object target, IEnumerable /// If we should throw an exception if the type can't be found. /// The type that was found or null. /// If we were unable to find the type. - public static Type ReallyFindType(string type, bool throwOnFailure) + public static Type? ReallyFindType(string? type, bool throwOnFailure) { - Type ret = typeCache.Get(type); + Type? ret = _typeCache.Get(type ?? string.Empty); if (ret != null || !throwOnFailure) { return ret; @@ -368,8 +382,8 @@ public static Type GetEventArgsTypeForEvent(Type type, string eventName) } Type ti = type; - EventInfo ei = ti.GetRuntimeEvent(eventName); - if (ei == null) + EventInfo? ei = ti.GetRuntimeEvent(eventName); + if (ei == null || ei.EventHandlerType == null) { throw new Exception($"Couldn't find {type.FullName}.{eventName}"); } @@ -414,7 +428,8 @@ public static bool IsStatic(this PropertyInfo item) throw new ArgumentNullException(nameof(item)); } - return (item.GetMethod ?? item.SetMethod).IsStatic; + var method = (item.GetMethod ?? item.SetMethod) !; + return method.IsStatic; } [SuppressMessage("Microsoft.Performance", "CA1801", Justification = "TViewModel used to help generic calling.")] @@ -424,7 +439,7 @@ internal static IObservable ViewModelWhenAnyValue(TVi { return view.WhenAnyValue(x => x.ViewModel) .Where(x => x != null) - .Select(x => ((TViewModel)x).WhenAnyDynamic(expression, y => y.Value)) + .Select(x => ((TViewModel)x!).WhenAnyDynamic(expression, y => y.Value)) .Switch(); } } diff --git a/src/ReactiveUI/Interactions/Interaction.cs b/src/ReactiveUI/Interactions/Interaction.cs index 7d96f54d6a..fb43e543ed 100644 --- a/src/ReactiveUI/Interactions/Interaction.cs +++ b/src/ReactiveUI/Interactions/Interaction.cs @@ -61,7 +61,7 @@ public class Interaction /// /// The scheduler to use when invoking handlers, which defaults to CurrentThreadScheduler.Instance if . /// - public Interaction(IScheduler handlerScheduler = null) + public Interaction(IScheduler? handlerScheduler = null) { _handlers = new List, IObservable>>(); _sync = new object(); @@ -180,7 +180,7 @@ public virtual IObservable Handle(TInput input) .Concat() .TakeWhile(_ => !context.IsHandled) .IgnoreElements() - .Select(_ => default(TOutput)) + .Select(_ => default(TOutput) !) .Concat( Observable.Defer( () => context.IsHandled diff --git a/src/ReactiveUI/Interactions/InteractionContext.cs b/src/ReactiveUI/Interactions/InteractionContext.cs index f868ac7423..c1a50dd5a6 100644 --- a/src/ReactiveUI/Interactions/InteractionContext.cs +++ b/src/ReactiveUI/Interactions/InteractionContext.cs @@ -27,7 +27,7 @@ namespace ReactiveUI public sealed class InteractionContext { private readonly TInput _input; - private TOutput _output; + private TOutput _output = default!; private int _outputSet; internal InteractionContext(TInput input) diff --git a/src/ReactiveUI/Interactions/UnhandledInteractionException.cs b/src/ReactiveUI/Interactions/UnhandledInteractionException.cs index a39c0d7c58..9abec96ccb 100644 --- a/src/ReactiveUI/Interactions/UnhandledInteractionException.cs +++ b/src/ReactiveUI/Interactions/UnhandledInteractionException.cs @@ -21,8 +21,8 @@ namespace ReactiveUI public class UnhandledInteractionException : Exception { [field: NonSerialized] - private readonly Interaction _interaction; - private readonly TInput _input; + private readonly Interaction? _interaction; + private readonly TInput _input = default!; /// /// Initializes a new instance of the class. @@ -70,13 +70,13 @@ public UnhandledInteractionException(string message, Exception innerException) protected UnhandledInteractionException(SerializationInfo info, StreamingContext context) : base(info, context) { - _input = (TInput)info.GetValue(nameof(Input), typeof(TInput)); + _input = (TInput)info.GetValue(nameof(Input), typeof(TInput)) !; } /// /// Gets the interaction that was not handled. /// - public Interaction Interaction => _interaction; + public Interaction? Interaction => _interaction; /// /// Gets the input for the interaction that was not handled. diff --git a/src/ReactiveUI/Interfaces/ICanActivate.cs b/src/ReactiveUI/Interfaces/ICanActivate.cs index 75a9e9eb0e..04faeb0d47 100644 --- a/src/ReactiveUI/Interfaces/ICanActivate.cs +++ b/src/ReactiveUI/Interfaces/ICanActivate.cs @@ -21,7 +21,7 @@ public interface ICanActivate IObservable Activated { get; } /// - /// Gets a obervable which is triggered when the ViewModel is deactivated. + /// Gets a observable which is triggered when the ViewModel is deactivated. /// IObservable Deactivated { get; } } diff --git a/src/ReactiveUI/Interfaces/ICreatesCommandBinding.cs b/src/ReactiveUI/Interfaces/ICreatesCommandBinding.cs index 1641893705..21b32d510e 100644 --- a/src/ReactiveUI/Interfaces/ICreatesCommandBinding.cs +++ b/src/ReactiveUI/Interfaces/ICreatesCommandBinding.cs @@ -38,14 +38,14 @@ public interface ICreatesCommandBinding /// /// The command to bind. /// The target object, usually a UI control of - /// some kind. + /// some kind. /// An IObservable source whose latest - /// value will be passed as the command parameter to the command. Hosts - /// will always pass a valid IObservable, but this may be - /// Observable.Empty. + /// value will be passed as the command parameter to the command. Hosts + /// will always pass a valid IObservable, but this may be + /// Observable.Empty. /// An IDisposable which will disconnect the binding when /// disposed. - IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter); + IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter); /// /// Bind an ICommand to a UI object to a specific event. This event may @@ -62,7 +62,7 @@ public interface ICreatesCommandBinding /// Observable.Empty. /// The event to bind to. /// An IDisposable which will disconnect the binding when disposed. - IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) + IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter, string eventName) #if MONO where TEventArgs : EventArgs #endif diff --git a/src/ReactiveUI/Interfaces/ICreatesObservableForProperty.cs b/src/ReactiveUI/Interfaces/ICreatesObservableForProperty.cs index 693f6010d2..3a053a5080 100644 --- a/src/ReactiveUI/Interfaces/ICreatesObservableForProperty.cs +++ b/src/ReactiveUI/Interfaces/ICreatesObservableForProperty.cs @@ -37,17 +37,17 @@ public interface ICreatesObservableForProperty : IEnableLogger /// /// The object to observe. /// The expression on the object to observe. - /// This will be either a MemberExpression or an IndexExpression - /// dependending on the property. + /// This will be either a MemberExpression or an IndexExpression + /// dependending on the property. /// /// The property of the type to query for. /// If true, signal just before the - /// property value actually changes. If false, signal after the - /// property changes. + /// property value actually changes. If false, signal after the + /// property changes. /// If true, no warnings should be logged. /// An IObservable which is signalled whenever the specified /// property on the object changes. If this cannot be done for a /// specified value of beforeChanged, return Observable.Never. - IObservable> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false); + IObservable>? GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false); } } diff --git a/src/ReactiveUI/Interfaces/IMessageBus.cs b/src/ReactiveUI/Interfaces/IMessageBus.cs index 54404df2a5..682898c41a 100644 --- a/src/ReactiveUI/Interfaces/IMessageBus.cs +++ b/src/ReactiveUI/Interfaces/IMessageBus.cs @@ -35,7 +35,7 @@ public interface IMessageBus : IEnableLogger /// A unique string to distinguish messages with /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. - void RegisterScheduler(IScheduler scheduler, string contract = null); + void RegisterScheduler(IScheduler scheduler, string? contract = null); /// /// Listen provides an Observable that will fire whenever a Message is @@ -46,7 +46,7 @@ public interface IMessageBus : IEnableLogger /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. /// An observable sequence. - IObservable Listen(string contract = null); + IObservable Listen(string? contract = null); /// /// ListenIncludeLatest provides an Observable that will fire whenever a Message is @@ -59,7 +59,7 @@ public interface IMessageBus : IEnableLogger /// only used for one purpose, leave this as null. /// An Observable representing the notifications posted to the /// message bus. - IObservable ListenIncludeLatest(string contract = null); + IObservable ListenIncludeLatest(string? contract = null); /// /// Determines if a particular message Type is registered. @@ -69,7 +69,7 @@ public interface IMessageBus : IEnableLogger /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. /// True if messages have been posted for this message Type. - bool IsRegistered(Type type, string contract = null); + bool IsRegistered(Type type, string? contract = null); /// /// Registers an Observable representing the stream of messages to send. @@ -83,7 +83,7 @@ public interface IMessageBus : IEnableLogger /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. /// A disposable. - IDisposable RegisterMessageSource(IObservable source, string contract = null); + IDisposable RegisterMessageSource(IObservable source, string? contract = null); /// /// Sends a single message using the specified Type and contract. @@ -96,6 +96,6 @@ public interface IMessageBus : IEnableLogger /// A unique string to distinguish messages with /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. - void SendMessage(T message, string contract = null); + void SendMessage(T message, string? contract = null); } } diff --git a/src/ReactiveUI/Interfaces/IPlatformOperations.cs b/src/ReactiveUI/Interfaces/IPlatformOperations.cs index 8d445c36ac..358213d571 100644 --- a/src/ReactiveUI/Interfaces/IPlatformOperations.cs +++ b/src/ReactiveUI/Interfaces/IPlatformOperations.cs @@ -15,6 +15,6 @@ internal interface IPlatformOperations /// of the screen. /// /// The device orientation descriptor. - string GetOrientation(); + string? GetOrientation(); } } diff --git a/src/ReactiveUI/Interfaces/IRoutableViewModel.cs b/src/ReactiveUI/Interfaces/IRoutableViewModel.cs index 3bee6b15f4..31474a74c2 100644 --- a/src/ReactiveUI/Interfaces/IRoutableViewModel.cs +++ b/src/ReactiveUI/Interfaces/IRoutableViewModel.cs @@ -13,7 +13,7 @@ public interface IRoutableViewModel : IReactiveObject /// /// Gets a string token representing the current ViewModel, such as 'login' or 'user'. /// - string UrlPathSegment { get; } + string? UrlPathSegment { get; } /// /// Gets the IScreen that this ViewModel is currently being shown in. This diff --git a/src/ReactiveUI/Interfaces/ISuspensionHost.cs b/src/ReactiveUI/Interfaces/ISuspensionHost.cs index 55517fe155..e882a43c39 100644 --- a/src/ReactiveUI/Interfaces/ISuspensionHost.cs +++ b/src/ReactiveUI/Interfaces/ISuspensionHost.cs @@ -63,7 +63,7 @@ public interface ISuspensionHost : IReactiveObject /// Gets or sets a function that can be used to create a new application state - usually /// this method just calls 'new' on an object. /// - Func CreateNewAppState { get; set; } + Func? CreateNewAppState { get; set; } /// /// Gets or sets the current application state - get a typed version of this via @@ -72,6 +72,6 @@ public interface ISuspensionHost : IReactiveObject /// via the client application - the framework places no restrictions on /// the object other than it can be serialized. /// - object AppState { get; set; } + object? AppState { get; set; } } } diff --git a/src/ReactiveUI/Interfaces/IViewFor.cs b/src/ReactiveUI/Interfaces/IViewFor.cs index d8874d1ccf..5569c99eaf 100644 --- a/src/ReactiveUI/Interfaces/IViewFor.cs +++ b/src/ReactiveUI/Interfaces/IViewFor.cs @@ -14,7 +14,7 @@ public interface IViewFor : IActivatableView /// /// Gets or sets the View Model associated with the View. /// - object ViewModel { get; set; } + object? ViewModel { get; set; } } #pragma warning disable SA1402 // File may only contain a single type @@ -30,6 +30,6 @@ public interface IViewFor : IViewFor /// Gets or sets the ViewModel corresponding to this specific View. This should be /// a DependencyProperty if you're using XAML. /// - new T ViewModel { get; set; } + new T? ViewModel { get; set; } } } diff --git a/src/ReactiveUI/Interfaces/IViewLocator.cs b/src/ReactiveUI/Interfaces/IViewLocator.cs index 51895be71a..30ecb65193 100644 --- a/src/ReactiveUI/Interfaces/IViewLocator.cs +++ b/src/ReactiveUI/Interfaces/IViewLocator.cs @@ -21,7 +21,6 @@ public interface IViewLocator : IEnableLogger /// viewModel. /// View model. /// Contract. - IViewFor ResolveView(T viewModel, string contract = null) - where T : class; + IViewFor? ResolveView(T viewModel, string? contract = null); } } diff --git a/src/ReactiveUI/Interfaces/ObservedChange.cs b/src/ReactiveUI/Interfaces/ObservedChange.cs index b39b625249..a0f48c7fb4 100644 --- a/src/ReactiveUI/Interfaces/ObservedChange.cs +++ b/src/ReactiveUI/Interfaces/ObservedChange.cs @@ -3,6 +3,7 @@ // 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; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq.Expressions; @@ -24,29 +25,20 @@ public class ObservedChange : IObservedChange /// The sender. /// Expression describing the member. /// The value. - public ObservedChange(TSender sender, Expression expression, TValue value = default(TValue)) + public ObservedChange(TSender sender, Expression expression, TValue value = default) { Sender = sender; Expression = expression; Value = value; } - /// - /// Gets the object which triggered the observed change. - /// -/// + /// public TSender Sender { get; private set; } - /// - /// Gets the Expression which was used to get the property changed value. - /// -/// + /// public Expression Expression { get; private set; } - /// - /// Gets the new value after the change. - /// -/// + /// public TValue Value { get; private set; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI/Legacy/RefcountDisposeWrapper.cs b/src/ReactiveUI/Legacy/RefcountDisposeWrapper.cs index cadf8b0d02..0e25d0c5d0 100644 --- a/src/ReactiveUI/Legacy/RefcountDisposeWrapper.cs +++ b/src/ReactiveUI/Legacy/RefcountDisposeWrapper.cs @@ -10,7 +10,7 @@ namespace ReactiveUI.Legacy { internal sealed class RefcountDisposeWrapper { - private IDisposable _inner; + private IDisposable? _inner; private int _refCount = 1; public RefcountDisposeWrapper(IDisposable inner) @@ -28,8 +28,8 @@ public void Release() if (Interlocked.Decrement(ref _refCount) == 0) { var inner = Interlocked.Exchange(ref _inner, null); - inner.Dispose(); + inner?.Dispose(); } } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI/Mixins/DependencyResolverMixins.cs b/src/ReactiveUI/Mixins/DependencyResolverMixins.cs index 93025d932b..6190477b26 100644 --- a/src/ReactiveUI/Mixins/DependencyResolverMixins.cs +++ b/src/ReactiveUI/Mixins/DependencyResolverMixins.cs @@ -44,7 +44,7 @@ public static void InitializeReactiveUI(this IMutableDependencyResolver resolver var fdr = typeof(DependencyResolverMixins); - var assemblyName = new AssemblyName(fdr.AssemblyQualifiedName.Replace(fdr.FullName + ", ", string.Empty)); + var assemblyName = new AssemblyName(fdr?.AssemblyQualifiedName?.Replace(fdr?.FullName + ", ", string.Empty) !); foreach (var ns in extraNs) { @@ -119,13 +119,16 @@ private static Func TypeFactory(TypeInfo typeInfo) private static void ProcessRegistrationForNamespace(string namespaceName, AssemblyName assemblyName, IMutableDependencyResolver resolver) { var targetType = namespaceName + ".Registrations"; - var fullName = targetType + ", " + assemblyName.FullName.Replace(assemblyName.Name, namespaceName); - - var registerTypeClass = Reflection.ReallyFindType(fullName, false); - if (registerTypeClass != null) + if (assemblyName.Name != null) { - var registerer = (IWantsToRegisterStuff)Activator.CreateInstance(registerTypeClass); - registerer.Register((f, t) => resolver.RegisterConstant(f(), t)); + var fullName = targetType + ", " + assemblyName.FullName.Replace(assemblyName.Name, namespaceName); + + var registerTypeClass = Reflection.ReallyFindType(fullName, false); + if (registerTypeClass != null) + { + var registerer = (IWantsToRegisterStuff)Activator.CreateInstance(registerTypeClass) !; + registerer?.Register((f, t) => resolver.RegisterConstant(f(), t)); + } } } } diff --git a/src/ReactiveUI/Mixins/ExpressionMixins.cs b/src/ReactiveUI/Mixins/ExpressionMixins.cs index 97fb1307fd..5567086ebe 100644 --- a/src/ReactiveUI/Mixins/ExpressionMixins.cs +++ b/src/ReactiveUI/Mixins/ExpressionMixins.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -130,7 +131,8 @@ public static Expression GetParent(this Expression expression) /// /// The expression. /// An array of arguments. - public static object[] GetArgumentsArray(this Expression expression) + [SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:ClosingSquareBracketsMustBeSpacedCorrectly", Justification = "Reviewed.")] + public static object[]? GetArgumentsArray(this Expression expression) { if (expression == null) { diff --git a/src/ReactiveUI/Mixins/ObservableLoggingMixin.cs b/src/ReactiveUI/Mixins/ObservableLoggingMixin.cs index 6f58ba2fbf..f8dee8101f 100644 --- a/src/ReactiveUI/Mixins/ObservableLoggingMixin.cs +++ b/src/ReactiveUI/Mixins/ObservableLoggingMixin.cs @@ -28,11 +28,11 @@ public static class ObservableLoggingMixin public static IObservable Log( this IObservable @this, TObj klass, - string message = null, - Func stringifier = null) + string? message = null, + Func? stringifier = null) where TObj : IEnableLogger { - message = message ?? string.Empty; + message ??= string.Empty; if (stringifier != null) { @@ -58,10 +58,10 @@ public static IObservable Log( /// The Observable to replace the current one OnError. /// An error message to print. /// The same Observable. - public static IObservable LoggedCatch(this IObservable @this, TObj klass, IObservable next = null, string message = null) + public static IObservable LoggedCatch(this IObservable @this, TObj klass, IObservable? next = null, string? message = null) where TObj : IEnableLogger { - next = next ?? Observable.Default; + next ??= Observable.Default; return @this.Catch(ex => { klass.Log().Warn(ex, message ?? string.Empty); @@ -81,7 +81,7 @@ public static IObservable LoggedCatch(this IObservable @this, TOb /// current one OnError. /// An error message to print. /// The same Observable. - public static IObservable LoggedCatch(this IObservable @this, TObj klass, Func> next, string message = null) + public static IObservable LoggedCatch(this IObservable @this, TObj klass, Func> next, string? message = null) where TObj : IEnableLogger where TException : Exception { diff --git a/src/ReactiveUI/Mixins/ObservedChangedMixin.cs b/src/ReactiveUI/Mixins/ObservedChangedMixin.cs index 0ae15c0ce4..12077898e4 100644 --- a/src/ReactiveUI/Mixins/ObservedChangedMixin.cs +++ b/src/ReactiveUI/Mixins/ObservedChangedMixin.cs @@ -97,6 +97,11 @@ public static IObservable Value( /// internal static bool TryGetValue(this IObservedChange item, out TValue changeValue) { + if (Equals(item.Sender, null)) + { + throw new ArgumentNullException(nameof(item), "Sender of the item is null"); + } + if (!Equals(item.Value, default(TValue))) { changeValue = item.Value; @@ -130,7 +135,10 @@ internal static void SetValueToProperty( TTarget target, Expression> property) { - Reflection.TrySetValueToPropertyChain(target, Reflection.Rewrite(property.Body).GetExpressionChain(), item.GetValue()); + if (target != null) + { + Reflection.TrySetValueToPropertyChain(target, Reflection.Rewrite(property.Body).GetExpressionChain(), item.GetValue()); + } } } } diff --git a/src/ReactiveUI/Mixins/ReactiveNotifyPropertyChangedMixin.cs b/src/ReactiveUI/Mixins/ReactiveNotifyPropertyChangedMixin.cs index f66cecc94c..9b6ebdb7d2 100644 --- a/src/ReactiveUI/Mixins/ReactiveNotifyPropertyChangedMixin.cs +++ b/src/ReactiveUI/Mixins/ReactiveNotifyPropertyChangedMixin.cs @@ -19,12 +19,12 @@ namespace ReactiveUI /// public static class ReactiveNotifyPropertyChangedMixin { - private static readonly MemoizingMRUCache<(Type senderType, string propertyName, bool beforeChange), ICreatesObservableForProperty> notifyFactoryCache = - new MemoizingMRUCache<(Type senderType, string propertyName, bool beforeChange), ICreatesObservableForProperty>( + private static readonly MemoizingMRUCache<(Type senderType, string propertyName, bool beforeChange), ICreatesObservableForProperty?> notifyFactoryCache = + new MemoizingMRUCache<(Type senderType, string propertyName, bool beforeChange), ICreatesObservableForProperty?>( (t, _) => { return Locator.Current.GetServices() - .Aggregate((score: 0, binding: (ICreatesObservableForProperty)null), (acc, x) => + .Aggregate((score: 0, binding: (ICreatesObservableForProperty?)null), (acc, x) => { int score = x.GetAffinityForObject(t.senderType, t.propertyName, t.beforeChange); return score > acc.score ? (score, x) : acc; @@ -146,8 +146,8 @@ public static IObservable> SubscribeToExpressio bool skipInitial = true, bool suppressWarnings = false) { - IObservable> notifier = - Observable.Return(new ObservedChange(null, null, source)); + IObservable> notifier = + Observable.Return(new ObservedChange(null, null!, source)); IEnumerable chain = Reflection.Rewrite(expression).GetExpressionChain(); notifier = chain.Aggregate(notifier, (n, expr) => n @@ -170,18 +170,18 @@ public static IObservable> SubscribeToExpressio throw new InvalidCastException($"Unable to cast from {val.GetType()} to {typeof(TValue)}."); } - return new ObservedChange(source, expression, (TValue)val); + return new ObservedChange(source, expression, (TValue)val!); }); return r.DistinctUntilChanged(x => x.Value); } - private static IObservedChange ObservedChangeFor(Expression expression, IObservedChange sourceChange) + private static IObservedChange ObservedChangeFor(Expression expression, IObservedChange sourceChange) { var propertyName = expression.GetMemberInfo().Name; if (sourceChange.Value == null) { - return new ObservedChange(sourceChange.Value, expression); + return new ObservedChange(sourceChange.Value, expression); } // expression is always a simple expression @@ -190,7 +190,7 @@ private static IObservedChange ObservedChangeFor(Expression expr return new ObservedChange(sourceChange.Value, expression, value); } - private static IObservable> NestedObservedChanges(Expression expression, IObservedChange sourceChange, bool beforeChange, bool suppressWarnings) + private static IObservable> NestedObservedChanges(Expression expression, IObservedChange sourceChange, bool beforeChange, bool suppressWarnings) { // Make sure a change at a root node propogates events down var kicker = ObservedChangeFor(expression, sourceChange); @@ -203,11 +203,11 @@ private static IObservable> NestedObservedChange // Handle non null values in the chain return NotifyForProperty(sourceChange.Value, expression, beforeChange, suppressWarnings) - .Select(x => new ObservedChange(x.Sender, expression, x.GetValue())) + .Select(x => new ObservedChange(x.Sender, expression, x.GetValue())) .StartWith(kicker); } - private static IObservable> NotifyForProperty(object sender, Expression expression, bool beforeChange, bool suppressWarnings) + private static IObservable>? NotifyForProperty(object sender, Expression expression, bool beforeChange, bool suppressWarnings) { var propertyName = expression.GetMemberInfo().Name; var result = notifyFactoryCache.Get((sender.GetType(), propertyName, beforeChange)); diff --git a/src/ReactiveUI/Observable.cs b/src/ReactiveUI/Observable.cs index e442dafa0d..a85d3b89c6 100644 --- a/src/ReactiveUI/Observable.cs +++ b/src/ReactiveUI/Observable.cs @@ -26,6 +26,6 @@ internal static class Observable /// /// An observable of type that ticks a single, default value. /// - public static readonly IObservable Default = Observable.Return(default(T)); + public static readonly IObservable Default = Observable.Return(default(T) !); } } diff --git a/src/ReactiveUI/ObservableForProperty/INPCObservableForProperty.cs b/src/ReactiveUI/ObservableForProperty/INPCObservableForProperty.cs index f939fa534d..75400dfe06 100644 --- a/src/ReactiveUI/ObservableForProperty/INPCObservableForProperty.cs +++ b/src/ReactiveUI/ObservableForProperty/INPCObservableForProperty.cs @@ -26,7 +26,7 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang /// [SuppressMessage("Roslynator", "RCS1211", Justification = "Neater with else clause.")] - public IObservable> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged, bool suppressWarnings = false) + public IObservable>? GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { if (expression == null) { @@ -49,8 +49,8 @@ public IObservable> GetNotificationForProperty(o void Handler(object eventSender, PropertyChangingEventArgs e) => eventHandler(e.PropertyName); return Handler; }, - x => before.PropertyChanging += x, - x => before.PropertyChanging -= x); + x => before!.PropertyChanging += x, + x => before!.PropertyChanging -= x); if (expression.NodeType == ExpressionType.Index) { @@ -71,8 +71,8 @@ public IObservable> GetNotificationForProperty(o void Handler(object eventSender, PropertyChangedEventArgs e) => eventHandler(e.PropertyName); return Handler; }, - x => after.PropertyChanged += x, - x => after.PropertyChanged -= x); + x => after!.PropertyChanged += x, + x => after!.PropertyChanged -= x); if (expression.NodeType == ExpressionType.Index) { diff --git a/src/ReactiveUI/ObservableForProperty/IROObservableForProperty.cs b/src/ReactiveUI/ObservableForProperty/IROObservableForProperty.cs index f0ba606cc7..c6fe5a1f9c 100644 --- a/src/ReactiveUI/ObservableForProperty/IROObservableForProperty.cs +++ b/src/ReactiveUI/ObservableForProperty/IROObservableForProperty.cs @@ -25,7 +25,7 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang } /// - public IObservable> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) + public IObservable>? GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { if (expression == null) { diff --git a/src/ReactiveUI/ObservableForProperty/OAPHCreationHelperMixin.cs b/src/ReactiveUI/ObservableForProperty/OAPHCreationHelperMixin.cs index 83a083dc64..7702884028 100644 --- a/src/ReactiveUI/ObservableForProperty/OAPHCreationHelperMixin.cs +++ b/src/ReactiveUI/ObservableForProperty/OAPHCreationHelperMixin.cs @@ -54,7 +54,7 @@ public static ObservableAsPropertyHelper ToProperty( Expression> property, TRet initialValue = default(TRet), bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) where TObj : class, IReactiveObject => source.ObservableToProperty(target, property, initialValue, deferSubscription, scheduler); /// @@ -100,7 +100,7 @@ public static ObservableAsPropertyHelper ToProperty( out ObservableAsPropertyHelper result, TRet initialValue = default(TRet), bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) where TObj : class, IReactiveObject { var ret = source.ObservableToProperty(target, property, initialValue, deferSubscription, scheduler); @@ -149,7 +149,7 @@ public static ObservableAsPropertyHelper ToProperty( string property, TRet initialValue = default(TRet), bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) where TObj : class, IReactiveObject => source.ObservableToProperty(target, property, initialValue, deferSubscription, scheduler); /// @@ -195,7 +195,7 @@ public static ObservableAsPropertyHelper ToProperty( out ObservableAsPropertyHelper result, TRet initialValue = default(TRet), bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) where TObj : class, IReactiveObject { result = source.ObservableToProperty( @@ -214,12 +214,23 @@ private static ObservableAsPropertyHelper ObservableToProperty Expression> property, TRet initialValue = default(TRet), bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) where TObj : class, IReactiveObject { - Contract.Requires(target != null); - Contract.Requires(observable != null); - Contract.Requires(property != null); + if (target == null) + { + throw new ArgumentNullException(nameof(target)); + } + + if (observable == null) + { + throw new ArgumentNullException(nameof(observable)); + } + + if (property == null) + { + throw new ArgumentNullException(nameof(property)); + } Expression expression = Reflection.Rewrite(property.Body); @@ -249,12 +260,23 @@ private static ObservableAsPropertyHelper ObservableToProperty string property, TRet initialValue = default(TRet), bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) where TObj : class, IReactiveObject { - Contract.Requires(target != null); - Contract.Requires(observable != null); - Contract.Requires(property != null); + if (target == null) + { + throw new ArgumentNullException(nameof(target)); + } + + if (observable == null) + { + throw new ArgumentNullException(nameof(observable)); + } + + if (property == null) + { + throw new ArgumentNullException(nameof(property)); + } return new ObservableAsPropertyHelper( observable, diff --git a/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs b/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs index cbf0c4515b..5634283b7c 100644 --- a/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs +++ b/src/ReactiveUI/ObservableForProperty/ObservableAsPropertyHelper.cs @@ -57,9 +57,9 @@ public sealed class ObservableAsPropertyHelper : IHandleObservableErrors, IDi public ObservableAsPropertyHelper( IObservable observable, Action onChanged, - T initialValue = default(T), + T initialValue = default, bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) : this(observable, onChanged, null, initialValue, deferSubscription, scheduler) { } @@ -94,10 +94,10 @@ public ObservableAsPropertyHelper( public ObservableAsPropertyHelper( IObservable observable, Action onChanged, - Action onChanging = null, - T initialValue = default(T), + Action? onChanging = null, + T initialValue = default, bool deferSubscription = false, - IScheduler scheduler = null) + IScheduler? scheduler = null) { Contract.Requires(observable != null); Contract.Requires(onChanged != null); @@ -111,7 +111,7 @@ public ObservableAsPropertyHelper( { onChanging(x); _lastValue = x; - onChanged(x); + onChanged!(x); }, ex => _thrownExceptions.Value.OnNext(ex)) .DisposeWith(_disposable); @@ -175,7 +175,7 @@ public T Value /// normally be a Dispatcher-based scheduler. /// /// A default property helper. - public static ObservableAsPropertyHelper Default(T initialValue = default(T), IScheduler scheduler = null) => + public static ObservableAsPropertyHelper Default(T initialValue = default, IScheduler? scheduler = null) => new ObservableAsPropertyHelper(Observable.Never, _ => { }, initialValue, false, scheduler); /// @@ -184,7 +184,7 @@ public T Value public void Dispose() { _disposable?.Dispose(); - _disposable = null; + _disposable = null!; } } } diff --git a/src/ReactiveUI/ObservableForProperty/POCOObservableForProperty.cs b/src/ReactiveUI/ObservableForProperty/POCOObservableForProperty.cs index 33864132f7..9ada9a71a9 100644 --- a/src/ReactiveUI/ObservableForProperty/POCOObservableForProperty.cs +++ b/src/ReactiveUI/ObservableForProperty/POCOObservableForProperty.cs @@ -28,7 +28,7 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang } /// - public IObservable> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) + public IObservable>? GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { if (sender == null) { diff --git a/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs b/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs index d0742329ce..220640d1b8 100644 --- a/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs +++ b/src/ReactiveUI/Platforms/android/AndroidObservableForWidgets.cs @@ -22,7 +22,7 @@ namespace ReactiveUI /// public class AndroidObservableForWidgets : ICreatesObservableForProperty { - private static readonly IDictionary<(Type viewType, string propertyName), Func>>> dispatchTable; + private static readonly Dictionary<(Type? viewType, string? propertyName), Func>>?> dispatchTable; static AndroidObservableForWidgets() { @@ -48,11 +48,11 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang return 0; } - return dispatchTable.Keys.Any(x => x.viewType.IsAssignableFrom(type) && x.propertyName == propertyName) ? 5 : 0; + return dispatchTable.Keys.Any(x => x.viewType != null && (x.viewType.IsAssignableFrom(type) && x.propertyName == propertyName)) ? 5 : 0; } /// - public IObservable> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) + public IObservable>? GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { if (sender == null) { @@ -60,9 +60,9 @@ public IObservable> GetNotificationForProperty(o } var type = sender.GetType(); - var tableItem = dispatchTable.Keys.First(x => x.viewType.IsAssignableFrom(type) && x.propertyName == propertyName); + var tableItem = dispatchTable.Keys.First(x => x.viewType != null && (x.viewType.IsAssignableFrom(type) && x.propertyName == propertyName)); - return dispatchTable[tableItem](sender, expression); + return dispatchTable[tableItem]?.Invoke(sender, expression); } private static DispatchItem CreateFromAdapterView() @@ -156,11 +156,11 @@ private static DispatchItem CreateFromWidget(Expression>> Func { get; set; } + public Func>>? Func { get; set; } } } } diff --git a/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs b/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs index 903b703f79..71c7f58af4 100644 --- a/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs +++ b/src/ReactiveUI/Platforms/android/AutoSuspendHelper.cs @@ -67,7 +67,7 @@ public AutoSuspendHelper(Application hostApplication) /// /// Gets or sets the latest bundle. /// - public static Bundle LatestBundle { get; set; } + public static Bundle? LatestBundle { get; set; } /// public void Dispose() diff --git a/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs b/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs index a92ea41326..20a3e53249 100644 --- a/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs +++ b/src/ReactiveUI/Platforms/android/BundleSuspensionDriver.cs @@ -46,7 +46,7 @@ public IObservable SaveState(object state) var serializer = new BinaryFormatter(); var st = new MemoryStream(); - AutoSuspendHelper.LatestBundle.PutByteArray("__state", st.ToArray()); + AutoSuspendHelper.LatestBundle?.PutByteArray("__state", st.ToArray()); return Observables.Unit; } catch (Exception ex) @@ -60,7 +60,7 @@ public IObservable InvalidateState() { try { - AutoSuspendHelper.LatestBundle.PutByteArray("__state", Array.Empty()); + AutoSuspendHelper.LatestBundle?.PutByteArray("__state", Array.Empty()); return Observables.Unit; } catch (Exception ex) diff --git a/src/ReactiveUI/Platforms/android/ContextExtensions.cs b/src/ReactiveUI/Platforms/android/ContextExtensions.cs index bbd71ab90e..a2b106a037 100644 --- a/src/ReactiveUI/Platforms/android/ContextExtensions.cs +++ b/src/ReactiveUI/Platforms/android/ContextExtensions.cs @@ -22,7 +22,7 @@ public static class ContextExtensions /// The Context to bind the Service from. /// Identifies the service to connect to. The Intent may specify either an explicit component name, or a logical description (action, category, etc) to match an IntentFilter published by a service. /// Operation options for the binding. The default is Bind.None. - public static IObservable ServiceBound(this Context context, Intent intent, Bind flags = Bind.None) + public static IObservable ServiceBound(this Context context, Intent intent, Bind flags = Bind.None) { return ServiceBound(context, intent, flags); } @@ -35,12 +35,10 @@ public static IObservable ServiceBound(this Context context, Intent int /// Identifies the service to connect to. The Intent may specify either an explicit component name, or a logical description (action, category, etc) to match an IntentFilter published by a service. /// Operation options for the binding. The default is Bind.None. /// The type of the returned service binder. - public static IObservable ServiceBound(this Context context, Intent intent, Bind flags = Bind.None) - where TBinder - : class, - IBinder + public static IObservable ServiceBound(this Context context, Intent intent, Bind flags = Bind.None) + where TBinder : class, IBinder { - return Observable.Create(observer => + return Observable.Create(observer => { var connection = new ServiceConnection(context, observer); try @@ -64,14 +62,14 @@ where TBinder /// /// The binder type. private class ServiceConnection : Java.Lang.Object, IServiceConnection - where TBinder : class, IBinder + where TBinder : class, IBinder { private readonly Context _context; - private readonly IObserver _observer; + private readonly IObserver _observer; private bool _disposed; - public ServiceConnection(Context context, IObserver observer) + public ServiceConnection(Context context, IObserver observer) { _context = context; _observer = observer; diff --git a/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs b/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs index 51b53e63a9..15a60be23f 100644 --- a/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs +++ b/src/ReactiveUI/Platforms/android/ControlFetcherMixin.cs @@ -33,7 +33,7 @@ private static readonly ConditionalWeakTable> v /// The activity. /// The property name. /// The return view. - public static View GetControl(this Activity activity, [CallerMemberName] string propertyName = null) + public static View GetControl(this Activity activity, [CallerMemberName] string? propertyName = null) => GetCachedControl(propertyName, activity, () => activity.FindViewById(GetControlIdByName(activity.GetType().Assembly, propertyName))); /// @@ -43,7 +43,7 @@ public static View GetControl(this Activity activity, [CallerMemberName] string /// The assembly containing the user-defined view. /// The property. /// The return view. - public static View GetControl(this View view, Assembly assembly, [CallerMemberName] string propertyName = null) + public static View GetControl(this View view, Assembly assembly, [CallerMemberName] string? propertyName = null) => GetCachedControl(propertyName, view, () => view.FindViewById(GetControlIdByName(assembly, propertyName))); /// @@ -63,7 +63,7 @@ public static void WireUpControls(this ILayoutViewHost layoutHost, ResolveStrate { try { - var view = layoutHost.View.GetControl(layoutHost.GetType().Assembly, member.GetResourceName()); + var view = layoutHost.View?.GetControl(layoutHost.GetType().Assembly, member.GetResourceName()); member.SetValue(layoutHost, view); } catch (Exception ex) @@ -197,8 +197,13 @@ internal static string GetResourceName(this PropertyInfo member) return resourceNameOverride ?? member.Name; } - private static View GetCachedControl(string propertyName, object rootView, Func fetchControlFromView) + private static View GetCachedControl(string? propertyName, object rootView, Func fetchControlFromView) { + if (propertyName == null) + { + throw new ArgumentNullException(nameof(propertyName)); + } + var ourViewCache = viewCache.GetOrCreateValue(rootView); if (ourViewCache.TryGetValue(propertyName, out View ret)) @@ -212,8 +217,13 @@ private static View GetCachedControl(string propertyName, object rootView, Func< return ret; } - private static int GetControlIdByName(Assembly assembly, string name) + private static int GetControlIdByName(Assembly assembly, string? name) { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + var ids = _controlIds.GetOrAdd( assembly, currentAssembly => diff --git a/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs b/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs index 15919e0c88..dabf3d764a 100644 --- a/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs +++ b/src/ReactiveUI/Platforms/android/FlexibleCommandBinder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -46,7 +47,7 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// - public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter) + public IDisposable? BindCommandToObject(ICommand command, object target, IObservable commandParameter) { if (target == null) { @@ -67,7 +68,7 @@ public IDisposable BindCommandToObject(ICommand command, object target, IObserva var typeProperties = _config[match]; - return typeProperties.CreateBinding(command, target, commandParameter); + return typeProperties.CreateBinding?.Invoke(command, target, commandParameter); } /// @@ -88,6 +89,7 @@ public IDisposable BindCommandToObject(ICommand command, object targ /// Command parameter. /// Event name. /// Enabled property name. + [SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "nullable object array.")] protected static IDisposable ForEvent(ICommand command, object target, IObservable commandParameter, string eventName, PropertyInfo enabledProperty) { if (command == null) @@ -97,7 +99,7 @@ protected static IDisposable ForEvent(ICommand command, object target, IObservab commandParameter = commandParameter ?? Observable.Return(target); - object latestParam = null; + object? latestParam = null; var ctl = target; var actionDisp = Observable.FromEventPattern(ctl, eventName).Subscribe(_ => @@ -108,7 +110,7 @@ protected static IDisposable ForEvent(ICommand command, object target, IObservab } }); - var enabledSetter = Reflection.GetValueSetterForProperty(enabledProperty); + Action? enabledSetter = Reflection.GetValueSetterForProperty(enabledProperty); if (enabledSetter == null) { return actionDisp; @@ -148,7 +150,7 @@ private class CommandBindingInfo { public int Affinity { get; set; } - public Func, IDisposable> CreateBinding { get; set; } + public Func, IDisposable>? CreateBinding { get; set; } } } } diff --git a/src/ReactiveUI/Platforms/android/ILayoutViewHost.cs b/src/ReactiveUI/Platforms/android/ILayoutViewHost.cs index c04ab433fb..5ffab914f1 100644 --- a/src/ReactiveUI/Platforms/android/ILayoutViewHost.cs +++ b/src/ReactiveUI/Platforms/android/ILayoutViewHost.cs @@ -18,6 +18,6 @@ public interface ILayoutViewHost /// /// The view. /// - View View { get; } + View? View { get; } } } diff --git a/src/ReactiveUI/Platforms/android/LayoutViewHost.cs b/src/ReactiveUI/Platforms/android/LayoutViewHost.cs index 7285c0ab7e..3fbe535590 100644 --- a/src/ReactiveUI/Platforms/android/LayoutViewHost.cs +++ b/src/ReactiveUI/Platforms/android/LayoutViewHost.cs @@ -17,7 +17,7 @@ namespace ReactiveUI /// public abstract class LayoutViewHost : ILayoutViewHost, IEnableLogger { - private View _view; + private View? _view; /// /// Initializes a new instance of the class. @@ -46,7 +46,7 @@ protected LayoutViewHost(Context ctx, int layoutId, ViewGroup parent, bool attac } /// - public View View + public View? View { get => _view; @@ -67,6 +67,6 @@ public View View /// /// The LayoutViewHost to cast. [SuppressMessage("Usage", "CA2225: Provide a method named ToView", Justification = "A property is already provided.")] - public static implicit operator View(LayoutViewHost layoutViewHost) => layoutViewHost?.View; + public static implicit operator View?(LayoutViewHost layoutViewHost) => layoutViewHost?.View; } } diff --git a/src/ReactiveUI/Platforms/android/LinkerOverrides.cs b/src/ReactiveUI/Platforms/android/LinkerOverrides.cs index b9718a3555..f95ce3cbfa 100644 --- a/src/ReactiveUI/Platforms/android/LinkerOverrides.cs +++ b/src/ReactiveUI/Platforms/android/LinkerOverrides.cs @@ -20,6 +20,7 @@ namespace ReactiveUI [Preserve(AllMembers = true)] internal class LinkerOverrides { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Used by linker.")] private void KeepMe() { var txt = new TextView(null); @@ -51,4 +52,4 @@ private void KeepMe() tp.Minute = tp.Minute; } } -} \ No newline at end of file +} diff --git a/src/ReactiveUI/Platforms/android/ObjectExtension.cs b/src/ReactiveUI/Platforms/android/ObjectExtension.cs index 46b9bc86c9..17b907562d 100644 --- a/src/ReactiveUI/Platforms/android/ObjectExtension.cs +++ b/src/ReactiveUI/Platforms/android/ObjectExtension.cs @@ -17,7 +17,7 @@ public static TObject ToNetObject(this Object value) { if (value == null) { - return default(TObject); + return default!; } if (!(value is JavaHolder)) @@ -28,7 +28,7 @@ public static TObject ToNetObject(this Object value) return (TObject)((JavaHolder)value).Instance; } - public static Object ToJavaObject(this TObject value) + public static Object? ToJavaObject(this TObject value) { if (value == null) { diff --git a/src/ReactiveUI/Platforms/android/PlatformOperations.cs b/src/ReactiveUI/Platforms/android/PlatformOperations.cs index ddf2bca00d..c6dc9a8f32 100644 --- a/src/ReactiveUI/Platforms/android/PlatformOperations.cs +++ b/src/ReactiveUI/Platforms/android/PlatformOperations.cs @@ -16,7 +16,7 @@ namespace ReactiveUI public class PlatformOperations : IPlatformOperations { /// - public string GetOrientation() + public string? GetOrientation() { var wm = Application.Context.GetSystemService(Context.WindowService) as IWindowManager; if (wm == null) diff --git a/src/ReactiveUI/Platforms/android/ReactiveActivity.cs b/src/ReactiveUI/Platforms/android/ReactiveActivity.cs index dad9fe4003..433578f39d 100644 --- a/src/ReactiveUI/Platforms/android/ReactiveActivity.cs +++ b/src/ReactiveUI/Platforms/android/ReactiveActivity.cs @@ -27,7 +27,7 @@ namespace ReactiveUI public class ReactiveActivity : ReactiveActivity, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -47,17 +47,17 @@ protected ReactiveActivity(IntPtr handle, JniHandleOwnership ownership) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get { return _viewModel; } set { this.RaiseAndSetIfChanged(ref _viewModel, value); } } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get { return _viewModel; } - set { _viewModel = (TViewModel)value; } + set { _viewModel = (TViewModel?)value; } } } @@ -90,10 +90,10 @@ protected ReactiveActivity(IntPtr handle, JniHandleOwnership ownership) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing diff --git a/src/ReactiveUI/Platforms/android/ReactiveFragment.cs b/src/ReactiveUI/Platforms/android/ReactiveFragment.cs index 4a6b49d6a0..fd910de3f4 100644 --- a/src/ReactiveUI/Platforms/android/ReactiveFragment.cs +++ b/src/ReactiveUI/Platforms/android/ReactiveFragment.cs @@ -24,7 +24,7 @@ namespace ReactiveUI public class ReactiveFragment : ReactiveFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -44,17 +44,17 @@ protected ReactiveFragment(IntPtr handle, JniHandleOwnership ownership) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value!; } } @@ -87,10 +87,10 @@ protected ReactiveFragment(IntPtr handle, JniHandleOwnership ownership) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs b/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs index a37f21248b..563306b176 100644 --- a/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs +++ b/src/ReactiveUI/Platforms/android/ReactivePreferenceActivity.cs @@ -27,7 +27,7 @@ namespace ReactiveUI public class ReactivePreferenceActivity : ReactivePreferenceActivity, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -47,17 +47,17 @@ protected ReactivePreferenceActivity(IntPtr handle, JniHandleOwnership ownership } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value!; } } @@ -90,10 +90,10 @@ protected ReactivePreferenceActivity(IntPtr handle, JniHandleOwnership ownership } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs b/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs index 3c3fb94b57..3d768fc1c9 100644 --- a/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs +++ b/src/ReactiveUI/Platforms/android/ReactivePreferenceFragment.cs @@ -24,7 +24,7 @@ namespace ReactiveUI public class ReactivePreferenceFragment : ReactivePreferenceFragment, IViewFor, ICanActivate where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -44,17 +44,17 @@ protected ReactivePreferenceFragment(IntPtr handle, JniHandleOwnership ownership } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => _viewModel; - set => _viewModel = (TViewModel)value; + set => _viewModel = (TViewModel?)value!; } } @@ -87,10 +87,10 @@ protected ReactivePreferenceFragment(IntPtr handle, JniHandleOwnership ownership } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs b/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs index b7c88a7a4e..59287b4bc7 100644 --- a/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs +++ b/src/ReactiveUI/Platforms/android/ReactiveViewHost.cs @@ -28,9 +28,9 @@ public abstract class ReactiveViewHost : LayoutViewHost, IViewFor allPublicProperties; + protected Lazy? allPublicProperties; - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -55,23 +55,23 @@ protected ReactiveViewHost() } /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public TViewModel ViewModel + public TViewModel? ViewModel { get { return _viewModel; } set { this.RaiseAndSetIfChanged(ref _viewModel, value); } } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get { return _viewModel; } - set { _viewModel = (TViewModel)value; } + set { _viewModel = (TViewModel?)value!; } } /// diff --git a/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs b/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs index 9fb5002ee4..6a88d3e35f 100644 --- a/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs +++ b/src/ReactiveUI/Platforms/android/UsbManagerExtensions.cs @@ -81,7 +81,7 @@ public UsbDevicePermissionReceiver(IObserver observer, UsbDevice device) public override void OnReceive(Context context, Intent intent) { var extraDevice = intent.GetParcelableExtra(UsbManager.ExtraDevice) as UsbDevice; - if (_device.DeviceName != extraDevice.DeviceName) + if (_device.DeviceName != extraDevice?.DeviceName) { return; } @@ -110,7 +110,7 @@ public UsbAccessoryPermissionReceiver(IObserver observer, UsbAccessory acc public override void OnReceive(Context context, Intent intent) { var extraAccessory = intent.GetParcelableExtra(UsbManager.ExtraAccessory) as UsbAccessory; - if (_accessory.Manufacturer != extraAccessory.Manufacturer || _accessory.Model != extraAccessory.Model) + if (_accessory.Manufacturer != extraAccessory?.Manufacturer || _accessory.Model != extraAccessory.Model) { return; } diff --git a/src/ReactiveUI/Platforms/android/ViewMixins.cs b/src/ReactiveUI/Platforms/android/ViewMixins.cs index 34dfb82ce3..af8d2a56a2 100644 --- a/src/ReactiveUI/Platforms/android/ViewMixins.cs +++ b/src/ReactiveUI/Platforms/android/ViewMixins.cs @@ -30,7 +30,7 @@ public static T GetViewHost(this View item) return tagData.ToNetObject(); } - return default; + return default!; } /// @@ -39,7 +39,7 @@ public static T GetViewHost(this View item) /// /// The view. /// The view host. - public static ILayoutViewHost GetViewHost(this View item) + public static ILayoutViewHost? GetViewHost(this View item) { return item?.GetTag(ViewHostTag)?.ToNetObject(); } diff --git a/src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs b/src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs index b235d25abe..359c5e4b20 100644 --- a/src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs +++ b/src/ReactiveUI/Platforms/android/WireUpResourceAttribute.cs @@ -24,7 +24,7 @@ public WireUpResourceAttribute() /// Initializes a new instance of the class. /// /// Name of the resource. - public WireUpResourceAttribute(string resourceName) + public WireUpResourceAttribute(string? resourceName) { ResourceNameOverride = resourceName; } @@ -32,6 +32,6 @@ public WireUpResourceAttribute(string resourceName) /// /// Gets the resource name override. /// - public string ResourceNameOverride { get; } + public string? ResourceNameOverride { get; } } } diff --git a/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeNSDateConverter.cs b/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeNSDateConverter.cs index 08f863f031..c1d6099742 100644 --- a/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeNSDateConverter.cs +++ b/src/ReactiveUI/Platforms/apple-common/Converters/DateTimeNSDateConverter.cs @@ -23,7 +23,7 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public bool TryConvert(object val, Type toType, object conversionHint, out object result) + public bool TryConvert(object? val, Type toType, object? conversionHint, out object? result) { result = null; diff --git a/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs b/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs index 25bb101efd..77498a53fc 100644 --- a/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs +++ b/src/ReactiveUI/Platforms/apple-common/IndexNormalizer.cs @@ -24,7 +24,7 @@ public static class IndexNormalizer /// /// The updates. /// A list updates. - public static IList Normalize(IEnumerable updates) + public static IList Normalize(IEnumerable updates) { var updatesList = updates.ToList(); MarkDuplicates(updatesList); diff --git a/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs b/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs index 2b975f6795..ebe26f54de 100644 --- a/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs +++ b/src/ReactiveUI/Platforms/apple-common/KVOObservableForProperty.cs @@ -67,7 +67,7 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang } /// - public IObservable> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) + public IObservable>? GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { var obj = sender as NSObject; if (obj == null) diff --git a/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs b/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs index 69e72301ea..12c313f513 100644 --- a/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs +++ b/src/ReactiveUI/Platforms/apple-common/ObservableForPropertyBase.cs @@ -57,7 +57,8 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang } /// - public IObservable> GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) + public IObservable>? GetNotificationForProperty( + object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { if (sender == null) { @@ -82,7 +83,7 @@ public IObservable> GetNotificationForProperty(o throw new NotSupportedException($"Notifications for {type.Name}.{propertyName} are not supported"); } - return match.CreateObservable((NSObject)sender, expression); + return match.CreateObservable?.Invoke((NSObject)sender, expression); } #if UIKIT @@ -158,8 +159,7 @@ protected static IObservable> ObservableFromEven /// Create observable. protected void Register(Type type, string property, int affinity, Func>> createObservable) { - Dictionary typeProperties; - if (!_config.TryGetValue(type, out typeProperties)) + if (!_config.TryGetValue(type, out Dictionary typeProperties)) { typeProperties = new Dictionary(); _config[type] = typeProperties; @@ -172,7 +172,7 @@ internal class ObservablePropertyInfo { public int Affinity { get; set; } - public Func>> CreateObservable { get; set; } + public Func>>? CreateObservable { get; set; } } } } diff --git a/src/ReactiveUI/Platforms/apple-common/PlatformOperations.cs b/src/ReactiveUI/Platforms/apple-common/PlatformOperations.cs index 8502a94bac..6a9990fc13 100644 --- a/src/ReactiveUI/Platforms/apple-common/PlatformOperations.cs +++ b/src/ReactiveUI/Platforms/apple-common/PlatformOperations.cs @@ -11,7 +11,7 @@ namespace ReactiveUI public class PlatformOperations : IPlatformOperations { /// - public string GetOrientation() + public string? GetOrientation() { #if UIKIT && !TVOS return UIKit.UIDevice.CurrentDevice.Orientation.ToString(); diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs index d4cadd9081..271d9c4229 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveControl.cs @@ -77,10 +77,10 @@ protected ReactiveControl(IntPtr handle) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -175,7 +175,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveControl : ReactiveControl, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -221,17 +221,17 @@ protected ReactiveControl(CGRect frame) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs index 28055676ed..003ad0c75a 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveImageView.cs @@ -100,10 +100,10 @@ protected ReactiveImageView(IntPtr handle) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); @@ -188,7 +188,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveImageView : ReactiveImageView, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -255,17 +255,17 @@ protected ReactiveImageView(IntPtr handle) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs index a8ac3e99cd..ae78cbadef 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveSplitViewController.cs @@ -79,10 +79,10 @@ protected ReactiveSplitViewController() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -181,7 +181,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveSplitViewController : ReactiveSplitViewController, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; #if UIKIT /// @@ -231,17 +231,17 @@ protected ReactiveSplitViewController() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveView.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveView.cs index 88291f1cc7..55427388b6 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveView.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveView.cs @@ -77,10 +77,10 @@ protected ReactiveView(CGRect frame) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable ThrownExceptions => this.GetThrownExceptionsObservable(); @@ -171,7 +171,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveView : ReactiveView, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -217,17 +217,17 @@ protected ReactiveView(CGRect frame) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/apple-common/ReactiveViewController.cs b/src/ReactiveUI/Platforms/apple-common/ReactiveViewController.cs index 5bfb518420..ecee9d49bc 100644 --- a/src/ReactiveUI/Platforms/apple-common/ReactiveViewController.cs +++ b/src/ReactiveUI/Platforms/apple-common/ReactiveViewController.cs @@ -77,10 +77,10 @@ protected ReactiveViewController(string nibNameOrNull, NSBundle nibBundleOrNull) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -178,7 +178,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveViewController : ReactiveViewController, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -225,17 +225,17 @@ protected ReactiveViewController(string nibNameOrNull, NSBundle nibBundleOrNull) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs b/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs index b99861f479..a5da064c3d 100644 --- a/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs +++ b/src/ReactiveUI/Platforms/apple-common/TargetActionCommandBinder.cs @@ -65,6 +65,7 @@ public int GetAffinityForObject(Type type, bool hasEventTarget) } /// + [SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "nullable object array.")] public IDisposable BindCommandToObject(ICommand command, object target, IObservable commandParameter) { if (command == null) @@ -79,7 +80,7 @@ public IDisposable BindCommandToObject(ICommand command, object target, IObserva commandParameter = commandParameter ?? Observable.Return(target); - object latestParam = null; + object? latestParam = null; var ctlDelegate = new ControlDelegate( x => { @@ -92,13 +93,13 @@ public IDisposable BindCommandToObject(ICommand command, object target, IObserva var sel = new Selector("theAction:"); // TODO how does this work? Is there an Action property? - Reflection.GetValueSetterOrThrow(target.GetType().GetRuntimeProperty("Action"))(target, sel, null); + Reflection.GetValueSetterOrThrow(target.GetType().GetRuntimeProperty("Action"))?.Invoke(target, sel, null); var targetSetter = Reflection.GetValueSetterOrThrow(target.GetType().GetRuntimeProperty("Target")); - targetSetter(target, ctlDelegate, null); - var actionDisp = Disposable.Create(() => targetSetter(target, null, null)); + targetSetter?.Invoke(target, ctlDelegate, null); + var actionDisp = Disposable.Create(() => targetSetter?.Invoke(target, null, null)); - var enabledSetter = Reflection.GetValueSetterForProperty(target.GetType().GetRuntimeProperty("Enabled")); + Action? enabledSetter = Reflection.GetValueSetterForProperty(target.GetType().GetRuntimeProperty("Enabled")); if (enabledSetter == null) { return actionDisp; diff --git a/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs b/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs index 0d9c8350db..db7d9807b9 100644 --- a/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs +++ b/src/ReactiveUI/Platforms/apple-common/ViewModelViewHost.cs @@ -27,11 +27,11 @@ namespace ReactiveUI public class ViewModelViewHost : ReactiveViewController { private readonly SerialDisposable _currentView; - private readonly ObservableAsPropertyHelper _viewContract; - private IViewLocator _viewLocator; - private NSViewController _defaultContent; - private IReactiveObject _viewModel; - private IObservable _viewContractObservable; + private readonly ObservableAsPropertyHelper _viewContract; + private IViewLocator? _viewLocator; + private NSViewController? _defaultContent; + private object? _viewModel; + private IObservable? _viewContractObservable; /// /// Initializes a new instance of the class. @@ -40,7 +40,7 @@ public ViewModelViewHost() { _currentView = new SerialDisposable(); _viewContract = this - .WhenAnyObservable(x => x.ViewContractObservable) + .WhenAnyObservable(x => x.ViewContractObservable!) .ToProperty(this, x => x.ViewContract, scheduler: RxApp.MainThreadScheduler); Initialize(); @@ -52,7 +52,7 @@ public ViewModelViewHost() /// /// The view locator. /// - public IViewLocator ViewLocator + public IViewLocator? ViewLocator { get => _viewLocator; set => this.RaiseAndSetIfChanged(ref _viewLocator, value); @@ -64,7 +64,7 @@ public IViewLocator ViewLocator /// /// The default content. /// - public NSViewController DefaultContent + public NSViewController? DefaultContent { get => _defaultContent; set => this.RaiseAndSetIfChanged(ref _defaultContent, value); @@ -73,7 +73,7 @@ public NSViewController DefaultContent /// /// Gets or sets the view model. /// - public IReactiveObject ViewModel + public object? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); @@ -82,7 +82,7 @@ public IReactiveObject ViewModel /// /// Gets or sets the view contract observable. /// - public IObservable ViewContractObservable + public IObservable? ViewContractObservable { get => _viewContractObservable; set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); @@ -91,7 +91,7 @@ public IObservable ViewContractObservable /// /// Gets or sets the view contract. /// - public string ViewContract + public string? ViewContract { get => _viewContract.Value; set => ViewContractObservable = Observable.Return(value); @@ -109,8 +109,13 @@ protected override void Dispose(bool disposing) } } - private static void Adopt(NSViewController parent, NSViewController child) + private static void Adopt(NSViewController parent, NSViewController? child) { + if (child == null) + { + return; + } + // ensure the child view fills our entire frame child.View.Frame = parent.View.Bounds; #if UIKIT @@ -157,7 +162,7 @@ private void Initialize() var viewChange = Observable .CombineLatest( this.WhenAnyValue(x => x.ViewModel), - this.WhenAnyObservable(x => x.ViewContractObservable).StartWith((string)null), + this.WhenAnyObservable(x => x.ViewContractObservable!).StartWith((string?)null), (vm, contract) => new { ViewModel = vm, Contract = contract }) .Where(x => x.ViewModel != null); @@ -175,11 +180,11 @@ private void Initialize() x => { var viewLocator = ViewLocator ?? ReactiveUI.ViewLocator.Current; - var view = viewLocator.ResolveView(x.ViewModel, x.Contract); + var view = viewLocator.ResolveView(x.ViewModel, x.Contract); if (view == null) { - var message = $"Unable to resolve view for \"{x.ViewModel.GetType()}\""; + var message = $"Unable to resolve view for \"{x.ViewModel?.GetType()}\""; if (x.Contract != null) { @@ -194,7 +199,7 @@ private void Initialize() if (viewController == null) { - throw new Exception($"Resolved view type '{viewController.GetType().FullName}' is not a '{typeof(NSViewController).FullName}'."); + throw new Exception($"Resolved view type '{viewController?.GetType().FullName}' is not a '{typeof(NSViewController).FullName}'."); } view.ViewModel = x.ViewModel; diff --git a/src/ReactiveUI/Platforms/ios/LinkerOverrides.cs b/src/ReactiveUI/Platforms/ios/LinkerOverrides.cs index 9ea70d374a..e6263ee871 100644 --- a/src/ReactiveUI/Platforms/ios/LinkerOverrides.cs +++ b/src/ReactiveUI/Platforms/ios/LinkerOverrides.cs @@ -14,6 +14,7 @@ namespace ReactiveUI.Cocoa [Preserve(AllMembers = true)] internal class LinkerOverrides { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Used by linker.")] public void KeepMe() { // UIButon diff --git a/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs b/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs index a092c3bbe8..92203fa8a1 100644 --- a/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs +++ b/src/ReactiveUI/Platforms/mac/ReactiveWindowController.cs @@ -84,10 +84,10 @@ protected ReactiveWindowController() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); diff --git a/src/ReactiveUI/Platforms/net4/ComponentModelTypeConverter.cs b/src/ReactiveUI/Platforms/net4/ComponentModelTypeConverter.cs index 0dc53c5b26..fc55982bb5 100644 --- a/src/ReactiveUI/Platforms/net4/ComponentModelTypeConverter.cs +++ b/src/ReactiveUI/Platforms/net4/ComponentModelTypeConverter.cs @@ -14,7 +14,7 @@ namespace ReactiveUI /// public class ComponentModelTypeConverter : IBindingTypeConverter { - private readonly MemoizingMRUCache<(Type fromType, Type toType), TypeConverter> _typeConverterCache = new MemoizingMRUCache<(Type fromType, Type toType), TypeConverter>( + private readonly MemoizingMRUCache<(Type fromType, Type toType), TypeConverter?> _typeConverterCache = new MemoizingMRUCache<(Type fromType, Type toType), TypeConverter?>( (types, _) => { // NB: String is a Magical Type(tm) to TypeConverters. If we are @@ -37,7 +37,7 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public bool TryConvert(object from, Type toType, object conversionHint, out object result) + public bool TryConvert(object? from, Type toType, object? conversionHint, out object? result) { if (from == null) { diff --git a/src/ReactiveUI/Platforms/netcoreapp3/ComponentModelTypeConverter.cs b/src/ReactiveUI/Platforms/netcoreapp3/ComponentModelTypeConverter.cs index 0dc53c5b26..759bfe773b 100644 --- a/src/ReactiveUI/Platforms/netcoreapp3/ComponentModelTypeConverter.cs +++ b/src/ReactiveUI/Platforms/netcoreapp3/ComponentModelTypeConverter.cs @@ -14,20 +14,29 @@ namespace ReactiveUI /// public class ComponentModelTypeConverter : IBindingTypeConverter { - private readonly MemoizingMRUCache<(Type fromType, Type toType), TypeConverter> _typeConverterCache = new MemoizingMRUCache<(Type fromType, Type toType), TypeConverter>( - (types, _) => - { - // NB: String is a Magical Type(tm) to TypeConverters. If we are - // converting from string => int, we need the Int converter, not - // the string converter :-/ - if (types.fromType == typeof(string)) - { - types = (types.toType, types.fromType); - } + private readonly MemoizingMRUCache<(Type fromType, Type toType), TypeConverter?> _typeConverterCache = + new MemoizingMRUCache<(Type fromType, Type toType), TypeConverter?>( + (types, _) => + { + // NB: String is a Magical Type(tm) to TypeConverters. If we are + // converting from string => int, we need the Int converter, not + // the string converter :-/ + if (types.fromType == typeof(string)) + { + types = (types.toType, + types.fromType); + } - var converter = TypeDescriptor.GetConverter(types.fromType); - return converter.CanConvertTo(types.toType) ? converter : null; - }, RxApp.SmallCacheLimit); + var converter = + TypeDescriptor + .GetConverter(types + .fromType); + return + converter + .CanConvertTo(types.toType) + ? converter + : null; + }, RxApp.SmallCacheLimit); /// public int GetAffinityForObjects(Type fromType, Type toType) @@ -37,7 +46,7 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public bool TryConvert(object from, Type toType, object conversionHint, out object result) + public bool TryConvert(object? @from, Type toType, object? conversionHint, out object? result) { if (from == null) { diff --git a/src/ReactiveUI/Platforms/tizen/PlatformOperations.cs b/src/ReactiveUI/Platforms/tizen/PlatformOperations.cs index 781a451100..9d6beed30b 100644 --- a/src/ReactiveUI/Platforms/tizen/PlatformOperations.cs +++ b/src/ReactiveUI/Platforms/tizen/PlatformOperations.cs @@ -11,7 +11,7 @@ namespace ReactiveUI public class PlatformOperations : IPlatformOperations { /// - public string GetOrientation() + public string? GetOrientation() { return null; } diff --git a/src/ReactiveUI/Platforms/tvos/LinkerOverrides.cs b/src/ReactiveUI/Platforms/tvos/LinkerOverrides.cs index 2076fb9fdd..dfccaf3424 100644 --- a/src/ReactiveUI/Platforms/tvos/LinkerOverrides.cs +++ b/src/ReactiveUI/Platforms/tvos/LinkerOverrides.cs @@ -14,6 +14,7 @@ namespace ReactiveUI.Cocoa [Preserve(AllMembers = true)] internal class LinkerOverrides { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Needed for linking.")] public void KeepMe() { // UIButon diff --git a/src/ReactiveUI/Platforms/uap/DependencyObjectObservableForProperty.cs b/src/ReactiveUI/Platforms/uap/DependencyObjectObservableForProperty.cs index acf0aca471..a7a79ab6ec 100644 --- a/src/ReactiveUI/Platforms/uap/DependencyObjectObservableForProperty.cs +++ b/src/ReactiveUI/Platforms/uap/DependencyObjectObservableForProperty.cs @@ -6,6 +6,7 @@ using System; using System.Diagnostics.Contracts; using System.Globalization; +using System.Linq.Expressions; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reflection; @@ -41,7 +42,7 @@ public int GetAffinityForObject(Type type, string propertyName, bool beforeChang } /// - public IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) + public IObservable>? GetNotificationForProperty(object sender, Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { if (sender == null) { @@ -94,7 +95,7 @@ public IObservable> GetNotificationForProperty(o }); } - private static PropertyInfo ActuallyGetProperty(TypeInfo typeInfo, string propertyName) + private static PropertyInfo? ActuallyGetProperty(TypeInfo typeInfo, string propertyName) { var current = typeInfo; while (current != null) @@ -111,7 +112,7 @@ private static PropertyInfo ActuallyGetProperty(TypeInfo typeInfo, string proper return null; } - private static FieldInfo ActuallyGetField(TypeInfo typeInfo, string propertyName) + private static FieldInfo? ActuallyGetField(TypeInfo typeInfo, string propertyName) { var current = typeInfo; while (current != null) @@ -128,7 +129,7 @@ private static FieldInfo ActuallyGetField(TypeInfo typeInfo, string propertyName return null; } - private static Func GetDependencyPropertyFetcher(Type type, string propertyName) + private static Func? GetDependencyPropertyFetcher(Type type, string propertyName) { var typeInfo = type.GetTypeInfo(); diff --git a/src/ReactiveUI/Platforms/uap/SingleWindowDispatcherScheduler.cs b/src/ReactiveUI/Platforms/uap/SingleWindowDispatcherScheduler.cs index 505c78df14..9a6736a63d 100644 --- a/src/ReactiveUI/Platforms/uap/SingleWindowDispatcherScheduler.cs +++ b/src/ReactiveUI/Platforms/uap/SingleWindowDispatcherScheduler.cs @@ -31,7 +31,7 @@ namespace ReactiveUI public class SingleWindowDispatcherScheduler : IScheduler { private const CoreDispatcherPriority Priority = default; - private static CoreDispatcher _dispatcher; + private static CoreDispatcher? _dispatcher; /// /// Initializes a new instance of the class. @@ -43,7 +43,7 @@ public SingleWindowDispatcherScheduler() return; } - CoreDispatcher coreDispatcher = TryGetDispatcher(); + CoreDispatcher? coreDispatcher = TryGetDispatcher(); Interlocked.CompareExchange(ref _dispatcher, coreDispatcher, null); } @@ -134,7 +134,7 @@ public IDisposable Schedule(TState state, DateTimeOffset dueTime, FuncThe exception. private static void RaiseUnhandledException(Exception ex) { - var timer = new DispatcherTimer + DispatcherTimer? timer = new DispatcherTimer { Interval = TimeSpan.Zero }; @@ -152,9 +152,9 @@ void RaiseToDispatcher(object sender, object e) } } - private static CoreDispatcher TryGetDispatcher() + private static CoreDispatcher? TryGetDispatcher() { - CoreDispatcher coreDispatcher; + CoreDispatcher? coreDispatcher; try { @@ -222,7 +222,7 @@ private IDisposable ScheduleSlow(TState state, TimeSpan dueTime, Func d.Disposable = ScheduleOnDispatcherNow(state, action), dueTime); + ThreadPoolTimer? timer = ThreadPoolTimer.CreateTimer(_ => d.Disposable = ScheduleOnDispatcherNow(state, action), dueTime); d.Disposable = Disposable.Create(() => { diff --git a/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs b/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs index 9fec6a82b1..2a44156c5a 100644 --- a/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs +++ b/src/ReactiveUI/Platforms/uikit-common/AutoSuspendHelper.cs @@ -76,7 +76,7 @@ public AutoSuspendHelper(UIApplicationDelegate appDelegate) /// /// The launch options. /// - public IDictionary LaunchOptions { get; private set; } + public IDictionary? LaunchOptions { get; private set; } /// /// Advances the finished launching observable. diff --git a/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs b/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs index c0cc4de90f..1208f1e4c1 100644 --- a/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs +++ b/src/ReactiveUI/Platforms/uikit-common/CollectionViewSectionInformation.cs @@ -20,13 +20,13 @@ namespace ReactiveUI public class CollectionViewSectionInformation : ISectionInformation { /// - public INotifyCollectionChanged Collection { get; protected set; } + public INotifyCollectionChanged? Collection { get; protected set; } /// - public Action InitializeCellAction { get; protected set; } + public Action? InitializeCellAction { get; protected set; } /// - public Func CellKeySelector { get; protected set; } + public Func? CellKeySelector { get; protected set; } } /// @@ -45,7 +45,7 @@ public class CollectionViewSectionInformation : CollectionViewSe /// The notify collection changed. /// The key selector function. /// The cell initialization action. - public CollectionViewSectionInformation(INotifyCollectionChanged collection, Func cellKeySelector, Action initializeCellAction = null) + public CollectionViewSectionInformation(INotifyCollectionChanged collection, Func cellKeySelector, Action? initializeCellAction = null) { Collection = collection; CellKeySelector = cellKeySelector; @@ -62,7 +62,7 @@ public CollectionViewSectionInformation(INotifyCollectionChanged collection, Fun /// The notify collection changed. /// The key selector function. /// The cell initialization action. - public CollectionViewSectionInformation(INotifyCollectionChanged collection, NSString cellKey, Action initializeCellAction = null) + public CollectionViewSectionInformation(INotifyCollectionChanged collection, NSString cellKey, Action? initializeCellAction = null) : this(collection, _ => cellKey, initializeCellAction) { } diff --git a/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs b/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs index e81855ed7c..631dd6e196 100644 --- a/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs +++ b/src/ReactiveUI/Platforms/uikit-common/CommonReactiveSource.cs @@ -87,7 +87,7 @@ public int RowsInSection(int section) { Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId, "The thread is not the main thread."); - var list = (IList)SectionInfo[section].Collection; + var list = (IList)SectionInfo[section].Collection!; var count = list.Count; this.Log().Debug(CultureInfo.InvariantCulture, "Reporting rows in section {0} = {1}", section, count); @@ -98,7 +98,7 @@ public object ItemAt(NSIndexPath path) { Debug.Assert(Thread.CurrentThread.ManagedThreadId == _mainThreadId, "The thread is not the main thread."); - var list = (IList)SectionInfo[path.Section].Collection; + var list = (IList)SectionInfo[path.Section].Collection!; this.Log().Debug(CultureInfo.InvariantCulture, "Returning item at {0}-{1}", path.Section, path.Row); return list[path.Row]; @@ -110,17 +110,16 @@ public TUIViewCell GetCell(NSIndexPath indexPath) this.Log().Debug(CultureInfo.InvariantCulture, "Getting cell for index path {0}-{1}", indexPath.Section, indexPath.Row); var section = SectionInfo[indexPath.Section]; - var vm = ((IList)section.Collection)[indexPath.Row]; - var cell = _adapter.DequeueReusableCell(section.CellKeySelector(vm), indexPath); - var view = cell as IViewFor; + var vm = ((IList)section.Collection!)[indexPath.Row]; + var cell = _adapter.DequeueReusableCell(section?.CellKeySelector?.Invoke(vm) ?? NSString.Empty, indexPath); - if (view != null) + if (cell is IViewFor view) { this.Log().Debug(CultureInfo.InvariantCulture, "Setting VM for index path {0}-{1}", indexPath.Section, indexPath.Row); view.ViewModel = vm; } - var initializeCellAction = section.InitializeCellAction ?? (_ => { }); + var initializeCellAction = section?.InitializeCellAction ?? (_ => { }); initializeCellAction(cell); return cell; @@ -390,7 +389,7 @@ private void ApplyPendingChanges(int sectionInfoId) foreach (var normalizedUpdate in normalizedUpdates) { - switch (normalizedUpdate.Type) + switch (normalizedUpdate?.Type) { case UpdateType.Add: DoUpdate(_adapter.InsertItems, new[] { normalizedUpdate.Index }, section); @@ -445,17 +444,17 @@ private sealed class PendingChange public PendingChange(NotifyCollectionChangedEventArgs ea) { Action = ea.Action; - OldItems = ea.OldItems == null ? null : ea.OldItems.Cast().ToList(); - NewItems = ea.NewItems == null ? null : ea.NewItems.Cast().ToList(); + OldItems = ea.OldItems?.Cast().ToList(); + NewItems = ea.NewItems?.Cast().ToList(); OldStartingIndex = ea.OldStartingIndex; NewStartingIndex = ea.NewStartingIndex; } public NotifyCollectionChangedAction Action { get; } - public IList OldItems { get; } + public IList? OldItems { get; } - public IList NewItems { get; } + public IList? NewItems { get; } public int OldStartingIndex { get; } diff --git a/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs b/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs index 480ea30365..ae56bd162f 100644 --- a/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs +++ b/src/ReactiveUI/Platforms/uikit-common/FlexibleCommandBinder.cs @@ -70,7 +70,7 @@ public IDisposable BindCommandToObject(ICommand command, object target, IObserva var typeProperties = _config[match]; - return typeProperties.CreateBinding(command, target, commandParameter); + return typeProperties?.CreateBinding?.Invoke(command, target, commandParameter) ?? Disposable.Empty; } /// @@ -96,9 +96,9 @@ protected static IDisposable ForEvent(ICommand command, object target, IObservab throw new ArgumentNullException(nameof(command)); } - commandParameter = commandParameter ?? Observable.Return(target); + commandParameter ??= Observable.Return(target); - object latestParam = null; + object? latestParam = null; var ctl = target; var actionDisp = Observable.FromEventPattern(ctl, eventName).Subscribe((e) => @@ -149,9 +149,9 @@ protected static IDisposable ForTargetAction(ICommand command, object target, IO commandParameter = commandParameter ?? Observable.Return(target); - object latestParam = null; + object? latestParam = null; - IDisposable actionDisp = null; + IDisposable actionDisposable = Disposable.Empty; var ctl = target as UIControl; if (ctl != null) @@ -165,20 +165,20 @@ protected static IDisposable ForTargetAction(ICommand command, object target, IO }); ctl.AddTarget(eh, UIControlEvent.TouchUpInside); - actionDisp = Disposable.Create(() => ctl.RemoveTarget(eh, UIControlEvent.TouchUpInside)); + actionDisposable = Disposable.Create(() => ctl.RemoveTarget(eh, UIControlEvent.TouchUpInside)); } var enabledSetter = Reflection.GetValueSetterForProperty(enabledProperty); if (enabledSetter == null) { - return actionDisp; + return actionDisposable; } // Initial enabled state enabledSetter(target, command.CanExecute(latestParam), null); return new CompositeDisposable( - actionDisp, + actionDisposable, commandParameter.Subscribe(x => latestParam = x), Observable.FromEvent( eventHandler => @@ -206,7 +206,7 @@ private class CommandBindingInfo { public int Affinity { get; set; } - public Func, IDisposable> CreateBinding { get; set; } + public Func, IDisposable>? CreateBinding { get; set; } } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs b/src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs index 5f6de23c15..21fefba0c9 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ISectionInformation.cs @@ -21,16 +21,16 @@ internal interface ISectionInformation /// /// Gets the collection. /// - INotifyCollectionChanged Collection { get; } + INotifyCollectionChanged? Collection { get; } /// /// Gets the cell key selector. /// - Func CellKeySelector { get; } + Func? CellKeySelector { get; } /// /// Gets the initialize cell action. /// - Action InitializeCellAction { get; } + Action? InitializeCellAction { get; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs index 1ee156e110..7109d5a06c 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionReusableView.cs @@ -70,10 +70,10 @@ protected ReactiveCollectionReusableView(NSCoder coder) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -159,7 +159,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveCollectionReusableView : ReactiveCollectionReusableView, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -205,17 +205,17 @@ protected ReactiveCollectionReusableView(CGRect frame) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs index 1187a8ce95..6a8a21b7fe 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionView.cs @@ -65,10 +65,10 @@ protected ReactiveCollectionView(NSCoder coder) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -153,7 +153,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveCollectionView : ReactiveCollectionView, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -193,17 +193,17 @@ protected ReactiveCollectionView(CGRect frame, UICollectionViewLayout layout) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs index 412fbd69e1..b49cc92460 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewCell.cs @@ -72,10 +72,10 @@ protected ReactiveCollectionViewCell(IntPtr handle) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -146,7 +146,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveCollectionViewCell : ReactiveCollectionViewCell, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -193,17 +193,17 @@ protected ReactiveCollectionViewCell(IntPtr handle) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs index 0606587953..8ccf7c1108 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewController.cs @@ -80,10 +80,10 @@ protected ReactiveCollectionViewController() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -163,7 +163,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveCollectionViewController : ReactiveCollectionViewController, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -219,17 +219,17 @@ protected ReactiveCollectionViewController() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs index 3235623b7d..7c37a774f9 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSource.cs @@ -33,7 +33,7 @@ public class ReactiveCollectionViewSource : UICollectionViewSource, IEn /// The notify collection chaged. /// The cell key. /// The cell initialization action. - public ReactiveCollectionViewSource(UICollectionView collectionView, INotifyCollectionChanged collection, NSString cellKey, Action initializeCellAction = null) + public ReactiveCollectionViewSource(UICollectionView collectionView, INotifyCollectionChanged collection, NSString cellKey, Action? initializeCellAction = null) : this(collectionView) { Data = new[] { new CollectionViewSectionInformation(collection, cellKey, initializeCellAction) }; @@ -62,10 +62,10 @@ public ReactiveCollectionViewSource(UICollectionView collectionView) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// /// Gets or sets the data that should be displayed by this diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs index 0a164226e9..d1e881a261 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveCollectionViewSourceExtensions.cs @@ -37,7 +37,7 @@ public static class ReactiveCollectionViewSourceExtensions public static IDisposable BindTo( this IObservable>> sectionsObservable, UICollectionView collectionView, - Func, IDisposable> initSource = null) + Func, IDisposable>? initSource = null) where TCell : UICollectionViewCell { var source = new ReactiveCollectionViewSource(collectionView); @@ -65,8 +65,8 @@ public static IDisposable BindTo( this IObservable sourceObservable, UICollectionView collectionView, NSString cellKey, - Action initializeCellAction = null, - Func, IDisposable> initSource = null) + Action? initializeCellAction = null, + Func, IDisposable>? initSource = null) where TCell : UICollectionViewCell { return sourceObservable @@ -98,8 +98,8 @@ public static IDisposable BindTo( public static IDisposable BindTo( this IObservable sourceObservable, UICollectionView collectionView, - Action initializeCellAction = null, - Func, IDisposable> initSource = null) + Action? initializeCellAction = null, + Func, IDisposable>? initSource = null) where TCell : UICollectionViewCell { if (collectionView == null) diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs index 3d04838bf7..dd152cfd75 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveNavigationController.cs @@ -89,10 +89,10 @@ protected ReactiveNavigationController() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -172,7 +172,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveNavigationController : ReactiveNavigationController, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -238,17 +238,17 @@ protected ReactiveNavigationController() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs index b4ee5b7c75..5e7cd0e2f1 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactivePageViewController.cs @@ -114,10 +114,10 @@ protected ReactivePageViewController() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -197,7 +197,7 @@ protected override void Dispose(bool disposing) public abstract class ReactivePageViewController : ReactivePageViewController, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -288,17 +288,17 @@ protected ReactivePageViewController() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs index d7e881effa..6105e7bba4 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTabBarController.cs @@ -70,10 +70,10 @@ protected ReactiveTabBarController() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -153,7 +153,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveTabBarController : ReactiveTabBarController, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -200,17 +200,17 @@ protected ReactiveTabBarController() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs index b5022f9714..f516e7bb98 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableView.cs @@ -81,10 +81,10 @@ protected ReactiveTableView(IntPtr handle) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -156,7 +156,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveTableView : ReactiveTableView, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -212,17 +212,17 @@ protected ReactiveTableView(IntPtr handle) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs index ab8b6d1a9a..f25b1abc2e 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewCell.cs @@ -92,10 +92,10 @@ protected ReactiveTableViewCell(IntPtr handle) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -166,7 +166,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveTableViewCell : ReactiveTableViewCell, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -233,17 +233,17 @@ protected ReactiveTableViewCell(IntPtr handle) } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs index 2d208130a5..632524d1f8 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewController.cs @@ -80,10 +80,10 @@ protected ReactiveTableViewController() } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// public IObservable> Changing => this.GetChangingObservable(); @@ -163,7 +163,7 @@ protected override void Dispose(bool disposing) public abstract class ReactiveTableViewController : ReactiveTableViewController, IViewFor where TViewModel : class { - private TViewModel _viewModel; + private TViewModel? _viewModel; /// /// Initializes a new instance of the class. @@ -219,17 +219,17 @@ protected ReactiveTableViewController() } /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => _viewModel; set => this.RaiseAndSetIfChanged(ref _viewModel, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel)value!; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs index cf782c2c7c..9d785bec0c 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSource.cs @@ -35,7 +35,7 @@ public class ReactiveTableViewSource : UITableViewSource, IEnableLogger /// The cell key. /// The size hint. /// The initialize cell action. - public ReactiveTableViewSource(UITableView tableView, INotifyCollectionChanged collection, NSString cellKey, float sizeHint, Action initializeCellAction = null) + public ReactiveTableViewSource(UITableView tableView, INotifyCollectionChanged collection, NSString cellKey, float sizeHint, Action? initializeCellAction = null) : this(tableView) { Data = new[] { new TableSectionInformation(collection, cellKey, sizeHint, initializeCellAction) }; @@ -61,10 +61,10 @@ public ReactiveTableViewSource(UITableView tableView) } /// - public event PropertyChangingEventHandler PropertyChanging; + public event PropertyChangingEventHandler? PropertyChanging; /// - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; /// /// Gets or sets the data that should be displayed by this @@ -246,28 +246,28 @@ public override nfloat GetHeightForFooter(UITableView tableView, nint section) } /// - public override string TitleForHeader(UITableView tableView, nint section) + public override string? TitleForHeader(UITableView tableView, nint section) { var header = _commonSource.SectionInfo[(int)section].Header; return header?.Title; } /// - public override string TitleForFooter(UITableView tableView, nint section) + public override string? TitleForFooter(UITableView tableView, nint section) { var footer = _commonSource.SectionInfo[(int)section].Footer; return footer?.Title; } /// - public override UIView GetViewForHeader(UITableView tableView, nint section) + public override UIView? GetViewForHeader(UITableView tableView, nint section) { var header = _commonSource.SectionInfo[(int)section].Header; return header?.View?.Invoke(); } /// - public override UIView GetViewForFooter(UITableView tableView, nint section) + public override UIView? GetViewForFooter(UITableView tableView, nint section) { var footer = _commonSource.SectionInfo[(int)section].Footer; return footer?.View?.Invoke(); diff --git a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs index 767f6881ac..cd827691e7 100644 --- a/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs +++ b/src/ReactiveUI/Platforms/uikit-common/ReactiveTableViewSourceExtensions.cs @@ -36,7 +36,7 @@ public static class ReactiveTableViewSourceExtensions public static IDisposable BindTo( this IObservable>> sectionsObservable, UITableView tableView, - Func, IDisposable> initSource = null) + Func, IDisposable>? initSource = null) where TCell : UITableViewCell { var source = new ReactiveTableViewSource(tableView); @@ -70,8 +70,8 @@ public static IDisposable BindTo( UITableView tableView, NSString cellKey, float sizeHint, - Action initializeCellAction = null, - Func, IDisposable> initSource = null) + Action? initializeCellAction = null, + Func, IDisposable>? initSource = null) where TCell : UITableViewCell { return sourceObservable @@ -105,8 +105,8 @@ public static IDisposable BindTo( this IObservable sourceObservable, UITableView tableView, float sizeHint, - Action initializeCellAction = null, - Func, IDisposable> initSource = null) + Action? initializeCellAction = null, + Func, IDisposable>? initSource = null) where TCell : UITableViewCell { if (tableView == null) diff --git a/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs b/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs index a073e2e834..f1ce138534 100644 --- a/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs +++ b/src/ReactiveUI/Platforms/uikit-common/RoutedViewHost.cs @@ -23,8 +23,8 @@ namespace ReactiveUI public class RoutedViewHost : ReactiveNavigationController { private readonly SerialDisposable _titleUpdater; - private RoutingState _router; - private IObservable _viewContractObservable; + private RoutingState _router = null!; + private IObservable? _viewContractObservable; private bool _routerInstigated; /// @@ -32,10 +32,10 @@ public class RoutedViewHost : ReactiveNavigationController /// public RoutedViewHost() { - ViewContractObservable = Observable.Return(null); + ViewContractObservable = Observable.Return(null); _titleUpdater = new SerialDisposable(); - this.WhenActivated( + _ = this.WhenActivated( d => { d(this @@ -44,45 +44,59 @@ public RoutedViewHost() .Subscribe(x => { _routerInstigated = true; - NSViewController view = null; + NSViewController? view = null; - foreach (var viewModel in x.NavigationStack) + if (Router != null && x != null) { - view = ResolveView(Router.GetCurrentViewModel(), null); - PushViewController(view, false); + foreach (var viewModel in x.NavigationStack) + { + view = ResolveView(Router.GetCurrentViewModel(), null); + if (view == null) + { + throw new NullReferenceException(nameof(view)); + } + + PushViewController(view, false); + } + + if (view != null) + { + _titleUpdater.Disposable = Router.GetCurrentViewModel() + .WhenAnyValue(y => y.UrlPathSegment) + .Subscribe(y => view.NavigationItem.Title = y); + } } - _titleUpdater.Disposable = Router.GetCurrentViewModel() - .WhenAnyValue(y => y.UrlPathSegment) - .Subscribe(y => view.NavigationItem.Title = y); - _routerInstigated = false; })); var navigationStackChanged = this.WhenAnyValue(x => x.Router) .Where(x => x != null) - .Select(x => x.NavigationStack.ObserveCollectionChanges()) + .Select(x => x?.NavigationStack.ObserveCollectionChanges()) .Switch(); d(navigationStackChanged .Where(x => x.EventArgs.Action == NotifyCollectionChangedAction.Add) - .Select(_ => new { View = ResolveView(Router.GetCurrentViewModel(), /*contract*/null), Animate = Router.NavigationStack.Count > 1 }) + .Select(_ => new { View = ResolveView(Router?.GetCurrentViewModel(), null), Animate = Router?.NavigationStack.Count > 1 }) .Subscribe(x => { - if (_routerInstigated) + if (_routerInstigated || Router == null) { return; } - _titleUpdater.Disposable = Router.GetCurrentViewModel() - .WhenAnyValue(y => y.UrlPathSegment) - .Subscribe(y => x.View.NavigationItem.Title = y); + if (x != null && x.View != null) + { + _titleUpdater.Disposable = Router.GetCurrentViewModel() + .WhenAnyValue(y => y.UrlPathSegment) + .Subscribe(y => x.View.NavigationItem.Title = y); + } _routerInstigated = true; // super important that animate is false if it's the first view being pushed, otherwise iOS gets hella confused // and calls PushViewController twice - PushViewController(x.View, x.Animate); + PushViewController(x?.View, x?.Animate ?? false); _routerInstigated = false; })); @@ -97,7 +111,7 @@ public RoutedViewHost() })); d(this - .WhenAnyObservable(x => x.Router.NavigateBack) + .WhenAnyObservable(x => x.Router!.NavigateBack!) .Subscribe(x => { _routerInstigated = true; @@ -119,7 +133,7 @@ public RoutingState Router /// /// Gets or sets the view contract observable. /// - public IObservable ViewContractObservable + public IObservable? ViewContractObservable { get => _viewContractObservable; set => this.RaiseAndSetIfChanged(ref _viewContractObservable, value); @@ -128,10 +142,10 @@ public IObservable ViewContractObservable /// /// Gets or sets the view locator. /// - public IViewLocator ViewLocator { get; set; } + public IViewLocator? ViewLocator { get; set; } /// - public override void PushViewController(NSViewController viewController, bool animated) + public override void PushViewController(NSViewController? viewController, bool animated) { if (viewController == null) { @@ -145,8 +159,11 @@ public override void PushViewController(NSViewController viewController, bool an // code must be pushing a view directly against nav controller rather than using the router, so we need to manually sync up the router state // TODO: what should we _actually_ do here? Soft-check the view and VM type and ignore if they're not IViewFor/IRoutableViewModel? var view = (IViewFor)viewController; - var viewModel = (IRoutableViewModel)view.ViewModel; - Router.NavigationStack.Add(viewModel); + var viewModel = (IRoutableViewModel?)view.ViewModel; + if (viewModel != null) + { + Router?.NavigationStack.Add(viewModel); + } } } @@ -156,7 +173,7 @@ public override NSViewController PopViewController(bool animated) if (!_routerInstigated) { // user must have clicked Back button in nav controller, so we need to manually sync up the router state - Router.NavigationStack.RemoveAt(_router.NavigationStack.Count - 1); + Router?.NavigationStack.RemoveAt(_router!.NavigationStack.Count - 1); } return base.PopViewController(animated); @@ -173,7 +190,7 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } - private NSViewController ResolveView(IRoutableViewModel viewModel, string contract) + private NSViewController? ResolveView(IRoutableViewModel? viewModel, string? contract) { if (viewModel == null) { diff --git a/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs b/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs index acf8f72a9e..1a03c78c73 100644 --- a/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs +++ b/src/ReactiveUI/Platforms/uikit-common/TableSectionHeader.cs @@ -37,7 +37,7 @@ public TableSectionHeader(string title) /// Gets or sets the function that creates the /// used as header for this section. Overrides Title. /// - public Func View { get; protected set; } + public Func? View { get; protected set; } /// /// Gets or sets the height of the header. @@ -47,6 +47,6 @@ public TableSectionHeader(string title) /// /// Gets or sets the title for the section header, only used if View is null. /// - public string Title { get; protected set; } + public string? Title { get; protected set; } } } diff --git a/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs b/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs index dfa7571098..e2875bf712 100644 --- a/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs +++ b/src/ReactiveUI/Platforms/uikit-common/TableSectionInformation.cs @@ -20,13 +20,13 @@ namespace ReactiveUI public class TableSectionInformation : ISectionInformation { /// - public INotifyCollectionChanged Collection { get; protected set; } + public INotifyCollectionChanged? Collection { get; protected set; } /// - public Action InitializeCellAction { get; protected set; } + public Action? InitializeCellAction { get; protected set; } /// - public Func CellKeySelector { get; protected set; } + public Func? CellKeySelector { get; protected set; } /// /// Gets or sets the size hint. @@ -37,13 +37,13 @@ public class TableSectionInformation : ISectionInformation /// The header, or null if a header shouldn't be used. - public TableSectionHeader Header { get; set; } + public TableSectionHeader? Header { get; set; } /// /// Gets or sets the footer of this section. /// /// The footer, or null if a footer shouldn't be used. - public TableSectionHeader Footer { get; set; } + public TableSectionHeader? Footer { get; set; } } /// @@ -63,7 +63,7 @@ public class TableSectionInformation : TableSectionInformationThe cell key selector. /// The size hint. /// The initialize cell action. - public TableSectionInformation(INotifyCollectionChanged collection, Func cellKeySelector, float sizeHint, Action initializeCellAction = null) + public TableSectionInformation(INotifyCollectionChanged collection, Func? cellKeySelector, float sizeHint, Action? initializeCellAction = null) { Collection = collection; SizeHint = sizeHint; @@ -81,7 +81,7 @@ public TableSectionInformation(INotifyCollectionChanged collection, FuncThe cell key. /// The size hint. /// The initialize cell action. - public TableSectionInformation(INotifyCollectionChanged collection, NSString cellKey, float sizeHint, Action initializeCellAction = null) + public TableSectionInformation(INotifyCollectionChanged collection, NSString cellKey, float sizeHint, Action? initializeCellAction = null) : this(collection, _ => cellKey, sizeHint, initializeCellAction) { } diff --git a/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs b/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs index 7cd17efbe1..124d44fdb9 100644 --- a/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs +++ b/src/ReactiveUI/Platforms/windows-common/AutoDataTemplateBindingHook.cs @@ -48,8 +48,8 @@ public class AutoDataTemplateBindingHook : IPropertyBindingHook "" + ""; - var assemblyName = typeof(AutoDataTemplateBindingHook).Assembly.FullName; - assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(',')); + string? assemblyName = typeof(AutoDataTemplateBindingHook).Assembly.FullName; + assemblyName = assemblyName?.Substring(0, assemblyName.IndexOf(',')); return (DataTemplate)XamlReader.Parse(template.Replace("__ASSEMBLYNAME__", assemblyName)); #endif diff --git a/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityTypeConverter.cs b/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityTypeConverter.cs index c24efa8775..a7428c1cae 100644 --- a/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityTypeConverter.cs +++ b/src/ReactiveUI/Platforms/windows-common/BooleanToVisibilityTypeConverter.cs @@ -39,17 +39,17 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public bool TryConvert(object from, Type toType, object conversionHint, out object result) + public bool TryConvert(object? from, Type toType, object? conversionHint, out object result) { var hint = conversionHint is BooleanToVisibilityHint ? (BooleanToVisibilityHint)conversionHint : BooleanToVisibilityHint.None; - if (toType == typeof(Visibility)) + if (toType == typeof(Visibility) && from is bool fromBool) { - var fromAsBool = hint.HasFlag(BooleanToVisibilityHint.Inverse) ? !(bool)@from : (bool)from; + var fromAsBool = (hint & BooleanToVisibilityHint.Inverse) != 0 ? !fromBool : fromBool; #if !NETFX_CORE && !HAS_UNO - var notVisible = hint.HasFlag(BooleanToVisibilityHint.UseHidden) ? Visibility.Hidden : Visibility.Collapsed; + var notVisible = (hint & BooleanToVisibilityHint.UseHidden) != 0 ? Visibility.Hidden : Visibility.Collapsed; #else var notVisible = Visibility.Collapsed; #endif @@ -57,8 +57,14 @@ public bool TryConvert(object from, Type toType, object conversionHint, out obje return true; } - var fromAsVis = (Visibility)from; - result = fromAsVis == Visibility.Visible ^ !hint.HasFlag(BooleanToVisibilityHint.Inverse); + if (from is Visibility fromAsVis) + { + result = fromAsVis == Visibility.Visible ^ (hint & BooleanToVisibilityHint.Inverse) == 0; + } + else + { + result = Visibility.Visible; + } return true; } diff --git a/src/ReactiveUI/Platforms/windows-common/PlatformOperations.cs b/src/ReactiveUI/Platforms/windows-common/PlatformOperations.cs index e5902dd3d0..6ab83e4abe 100644 --- a/src/ReactiveUI/Platforms/windows-common/PlatformOperations.cs +++ b/src/ReactiveUI/Platforms/windows-common/PlatformOperations.cs @@ -21,7 +21,7 @@ namespace ReactiveUI public class PlatformOperations : IPlatformOperations { /// - public string GetOrientation() + public string? GetOrientation() { #if NETFX_CORE || HAS_UNO try diff --git a/src/ReactiveUI/Platforms/windows-common/ReactivePage.cs b/src/ReactiveUI/Platforms/windows-common/ReactivePage.cs index d96c196143..f11caee934 100644 --- a/src/ReactiveUI/Platforms/windows-common/ReactivePage.cs +++ b/src/ReactiveUI/Platforms/windows-common/ReactivePage.cs @@ -149,20 +149,20 @@ protected ReactivePage(IntPtr handle) /// /// Gets the binding root view model. /// - public TViewModel BindingRoot => ViewModel; + public TViewModel? BindingRoot => ViewModel; /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } } } diff --git a/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs b/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs index f76ec83696..c80ded4c00 100644 --- a/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs +++ b/src/ReactiveUI/Platforms/windows-common/ReactiveUserControl.cs @@ -149,20 +149,20 @@ protected ReactiveUserControl(IntPtr handle) /// /// Gets the binding root view model. /// - public TViewModel BindingRoot => ViewModel; + public TViewModel? BindingRoot => ViewModel; /// - public TViewModel ViewModel + public TViewModel? ViewModel { get => (TViewModel)GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); } /// - object IViewFor.ViewModel + object? IViewFor.ViewModel { get => ViewModel; - set => ViewModel = (TViewModel)value; + set => ViewModel = (TViewModel?)value; } } } diff --git a/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs b/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs index c1bdbddcd8..8bdc27fb6b 100644 --- a/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs +++ b/src/ReactiveUI/Platforms/windows-common/RoutedViewHost.cs @@ -73,7 +73,7 @@ public RoutedViewHost() } var platform = Locator.Current.GetService(); - Func platformGetter = () => default(string); + Func platformGetter = () => default!; if (platform == null) { @@ -86,7 +86,7 @@ public RoutedViewHost() platformGetter = () => platform.GetOrientation(); } - ViewContractObservable = Observable.FromEvent( + ViewContractObservable = Observable.FromEvent( eventHandler => { void Handler(object sender, SizeChangedEventArgs e) => eventHandler(platformGetter()); @@ -99,7 +99,7 @@ public RoutedViewHost() .Select(x => x); var vmAndContract = Observable.CombineLatest( - this.WhenAnyObservable(x => x.Router.CurrentViewModel), + this.WhenAnyObservable(x => x.Router.CurrentViewModel!), this.WhenAnyObservable(x => x.ViewContractObservable), (viewModel, contract) => (viewModel, contract)); @@ -127,7 +127,7 @@ public RoutedViewHost() view.ViewModel = x.viewModel; Content = view; - }, ex => RxApp.DefaultExceptionHandler.OnNext(ex))); + }, ex => RxApp.DefaultExceptionHandler?.OnNext(ex))); }); } @@ -156,9 +156,9 @@ public object DefaultContent /// /// The view contract observable. /// - public IObservable ViewContractObservable + public IObservable ViewContractObservable { - get => (IObservable)GetValue(ViewContractObservableProperty); + get => (IObservable)GetValue(ViewContractObservableProperty); set => SetValue(ViewContractObservableProperty, value); } @@ -168,6 +168,6 @@ public IObservable ViewContractObservable /// /// The view locator. /// - public IViewLocator ViewLocator { get; set; } + public IViewLocator? ViewLocator { get; set; } } } diff --git a/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs b/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs index 3db6ceba14..b30992ecb8 100644 --- a/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs +++ b/src/ReactiveUI/Platforms/windows-common/ViewModelViewHost.cs @@ -31,6 +31,7 @@ namespace ReactiveUI /// inside a DataTemplate to display the View associated with a ViewModel. /// [SuppressMessage("Design", "CA1010:Collections should implement generic interface", Justification = "Deliberate usage")] + public #if HAS_UNO partial @@ -62,7 +63,7 @@ class ViewModelViewHost : TransitioningContentControl, IViewFor, IEnableLogger private readonly Subject _updateViewModel = new Subject(); private readonly Subject _updateViewContract = new Subject(); - private string _viewContract; + private string? _viewContract; private bool _isDisposed; /// @@ -83,7 +84,7 @@ public ViewModelViewHost() } var platform = Locator.Current.GetService(); - Func platformGetter = () => default(string); + Func platformGetter = () => default; if (platform == null) { @@ -104,12 +105,12 @@ public ViewModelViewHost() vmAndContract.Subscribe(x => ResolveViewForViewModel(x.ViewModel, x.Contract)); contractChanged .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(x => _viewContract = x); + .Subscribe(x => _viewContract = x ?? string.Empty); ViewContractObservable = Observable.FromEvent( eventHandler => { - void Handler(object sender, SizeChangedEventArgs e) => eventHandler(platformGetter()); + void Handler(object sender, SizeChangedEventArgs e) => eventHandler(platformGetter() !); return Handler; }, x => SizeChanged += x, @@ -121,7 +122,7 @@ public ViewModelViewHost() /// /// Gets or sets the view contract observable. /// - public IObservable ViewContractObservable + public IObservable ViewContractObservable { get => (IObservable)GetValue(ViewContractObservableProperty); set => SetValue(ViewContractObservableProperty, value); @@ -139,7 +140,7 @@ public object DefaultContent /// /// Gets or sets the ViewModel to display. /// - public object ViewModel + public object? ViewModel { get => GetValue(ViewModelProperty); set => SetValue(ViewModelProperty, value); @@ -148,7 +149,7 @@ public object ViewModel /// /// Gets or sets the view contract. /// - public string ViewContract + public string? ViewContract { get => _viewContract; set => ViewContractObservable = Observable.Return(value); @@ -157,7 +158,7 @@ public string ViewContract /// /// Gets or sets the view locator. /// - public IViewLocator ViewLocator { get; set; } + public IViewLocator? ViewLocator { get; set; } /// public void Dispose() @@ -196,7 +197,7 @@ private static void ViewContractChanged(DependencyObject dependencyObject, Depen ((ViewModelViewHost)dependencyObject)._updateViewContract.OnNext(Unit.Default); } - private void ResolveViewForViewModel(object viewModel, string contract) + private void ResolveViewForViewModel(object? viewModel, string? contract) { if (viewModel == null) { diff --git a/src/ReactiveUI/Platforms/xamarin-common/ComponentModelTypeConverter.cs b/src/ReactiveUI/Platforms/xamarin-common/ComponentModelTypeConverter.cs index c7a5ed75f6..8fd4472db3 100644 --- a/src/ReactiveUI/Platforms/xamarin-common/ComponentModelTypeConverter.cs +++ b/src/ReactiveUI/Platforms/xamarin-common/ComponentModelTypeConverter.cs @@ -14,7 +14,7 @@ namespace ReactiveUI /// public class ComponentModelTypeConverter : IBindingTypeConverter { - private readonly MemoizingMRUCache<(Type fromType, Type toType), TypeConverter> _typeConverterCache = new MemoizingMRUCache<(Type fromType, Type toType), TypeConverter>( + private readonly MemoizingMRUCache<(Type fromType, Type toType), TypeConverter?> _typeConverterCache = new MemoizingMRUCache<(Type fromType, Type toType), TypeConverter?>( (types, _) => { // NB: String is a Magical Type(tm) to TypeConverters. If we are @@ -37,7 +37,7 @@ public int GetAffinityForObjects(Type fromType, Type toType) } /// - public bool TryConvert(object from, Type toType, object conversionHint, out object result) + public bool TryConvert(object? from, Type toType, object? conversionHint, out object? result) { if (from == null) { diff --git a/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs b/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs index f7d3216103..3ea3f60d68 100644 --- a/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs +++ b/src/ReactiveUI/ReactiveCommand/ReactiveCommand.cs @@ -92,8 +92,8 @@ public static class ReactiveCommand /// public static ReactiveCommand Create( Action execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { if (execute == null) { @@ -134,8 +134,8 @@ public static ReactiveCommand Create( /// public static ReactiveCommand Create( Func execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { if (execute == null) { @@ -174,8 +174,8 @@ public static ReactiveCommand Create( /// public static ReactiveCommand Create( Action execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { if (execute == null) { @@ -219,8 +219,8 @@ public static ReactiveCommand Create( /// public static ReactiveCommand Create( Func execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { if (execute == null) { @@ -259,8 +259,8 @@ public static ReactiveCommand Create( /// public static ReactiveCommand CreateFromObservable( Func> execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { if (execute == null) { @@ -293,8 +293,8 @@ public static ReactiveCommand CreateFromObservable( /// public static ReactiveCommand CreateFromTask( Func> execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( () => execute().ToObservable(), @@ -322,8 +322,8 @@ public static ReactiveCommand CreateFromTask( /// public static ReactiveCommand CreateFromTask( Func> execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( () => Observable.StartAsync(execute), @@ -348,8 +348,8 @@ public static ReactiveCommand CreateFromTask( /// public static ReactiveCommand CreateFromTask( Func execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( () => execute().ToObservable(), @@ -374,8 +374,8 @@ public static ReactiveCommand CreateFromTask( /// public static ReactiveCommand CreateFromTask( Func execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( () => Observable.StartAsync(execute), @@ -406,8 +406,8 @@ public static ReactiveCommand CreateFromTask( /// public static ReactiveCommand CreateFromObservable( Func> execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return new ReactiveCommand( execute, @@ -438,8 +438,8 @@ public static ReactiveCommand CreateFromObservable public static ReactiveCommand CreateFromTask( Func> execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( param => execute(param).ToObservable(), @@ -470,8 +470,8 @@ public static ReactiveCommand CreateFromTask( /// public static ReactiveCommand CreateFromTask( Func> execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( param => Observable.StartAsync(ct => execute(param, ct)), @@ -499,8 +499,8 @@ public static ReactiveCommand CreateFromTask( /// public static ReactiveCommand CreateFromTask( Func execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( param => execute(param).ToObservable(), @@ -528,8 +528,8 @@ public static ReactiveCommand CreateFromTask( /// public static ReactiveCommand CreateFromTask( Func execute, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return CreateFromObservable( param => Observable.StartAsync(ct => execute(param, ct)), @@ -561,8 +561,8 @@ public static ReactiveCommand CreateFromTask( /// public static CombinedReactiveCommand CreateCombined( IEnumerable> childCommands, - IObservable canExecute = null, - IScheduler outputScheduler = null) + IObservable? canExecute = null, + IScheduler? outputScheduler = null) { return new CombinedReactiveCommand(childCommands, canExecute ?? Observables.True, outputScheduler ?? RxApp.MainThreadScheduler); } @@ -606,8 +606,8 @@ public class ReactiveCommand : ReactiveCommandBaseThrown if any dependent parameters are null. protected internal ReactiveCommand( Func> execute, - IObservable canExecute, - IScheduler outputScheduler) + IObservable? canExecute, + IScheduler? outputScheduler) { if (execute == null) { @@ -751,13 +751,13 @@ private ExecutionInfo(ExecutionDemarcation demarcation, TResult result) public TResult Result => _result; public static ExecutionInfo CreateBegin() => - new ExecutionInfo(ExecutionDemarcation.Begin, default(TResult)); + new ExecutionInfo(ExecutionDemarcation.Begin, default!); public static ExecutionInfo CreateResult(TResult result) => new ExecutionInfo(ExecutionDemarcation.Result, result); public static ExecutionInfo CreateEnd() => - new ExecutionInfo(ExecutionDemarcation.End, default(TResult)); + new ExecutionInfo(ExecutionDemarcation.End, default!); } } } diff --git a/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs b/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs index 184c0d9df8..49c5e3c740 100644 --- a/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs +++ b/src/ReactiveUI/ReactiveCommand/ReactiveCommandBase.cs @@ -73,7 +73,7 @@ namespace ReactiveUI /// public abstract class ReactiveCommandBase : IObservable, ICommand, IReactiveCommand { - private EventHandler _canExecuteChanged; + private EventHandler? _canExecuteChanged; private bool _canExecuteValue; /// @@ -213,7 +213,7 @@ protected virtual bool ICommandCanExecute(object parameter) /// This method is called when the Command should execute. /// /// The parameter being passed to the ICommand. - protected virtual void ICommandExecute(object parameter) + protected virtual void ICommandExecute(object? parameter) { // ensure that null is coerced to default(TParam) so that commands taking value types will use a sensible default if no parameter is supplied if (parameter == null) @@ -227,7 +227,7 @@ protected virtual void ICommandExecute(object parameter) $"Command requires parameters of type {typeof(TParam).FullName}, but received parameter of type {parameter.GetType().FullName}."); } - Execute((TParam)parameter) + Execute((TParam)parameter!) .Catch(Observable.Empty) .Subscribe(); } diff --git a/src/ReactiveUI/ReactiveCommand/ReactiveCommandMixins.cs b/src/ReactiveUI/ReactiveCommand/ReactiveCommandMixins.cs index 564075616d..8cae8f3169 100644 --- a/src/ReactiveUI/ReactiveCommand/ReactiveCommandMixins.cs +++ b/src/ReactiveUI/ReactiveCommand/ReactiveCommandMixins.cs @@ -31,7 +31,7 @@ public static IDisposable InvokeCommand(this IObservable item, ICommand co var canExecuteChanged = Observable.FromEvent( eventHandler => { - void Handler(object sender, EventArgs e) => eventHandler(Unit.Default); + void Handler(object? sender, EventArgs e) => eventHandler(Unit.Default); return Handler; }, h => command.CanExecuteChanged += h, @@ -87,11 +87,7 @@ public static IDisposable InvokeCommand(this IObservable item, TT var commandCanExecuteChanged = commandObs .Select(command => command == null ? Observable.Empty : Observable .FromEvent( - eventHandler => - { - void Handler(object sender, EventArgs e) => eventHandler(command); - return Handler; - }, + eventHandler => (sender, e) => eventHandler(command), h => command.CanExecuteChanged += h, h => command.CanExecuteChanged -= h) .StartWith(command)) @@ -123,7 +119,7 @@ public static IDisposable InvokeCommand(this IObservable var invocationInfo = command .Select(cmd => cmd == null ? Observable, T>>.Empty : cmd .CanExecute - .Select(canExecute => InvokeCommandInfo.From(cmd, canExecute, default(T)))) + .Select(canExecute => InvokeCommandInfo.From(cmd, canExecute, default(T) !))) .Switch(); return WithLatestFromFixed(item, invocationInfo, (value, ii) => ii.WithValue(value)) diff --git a/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs b/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs index c8dbe89ce0..34436f99e7 100644 --- a/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs +++ b/src/ReactiveUI/ReactiveObject/IReactiveObjectExtensions.cs @@ -115,10 +115,13 @@ public static TRet RaiseAndSetIfChanged( this TObj reactiveObject, ref TRet backingField, TRet newValue, - [CallerMemberName] string propertyName = null) + [CallerMemberName] string? propertyName = null) where TObj : IReactiveObject { - Contract.Requires(propertyName != null); + if (propertyName == null) + { + throw new ArgumentNullException(nameof(propertyName)); + } if (EqualityComparer.Default.Equals(backingField, newValue)) { @@ -141,10 +144,13 @@ public static TRet RaiseAndSetIfChanged( /// A string representing the name of the property that has been changed. /// Leave null to let the runtime set to caller member name. /// - public static void RaisePropertyChanged(this TSender reactiveObject, [CallerMemberName] string propertyName = null) + public static void RaisePropertyChanged(this TSender reactiveObject, [CallerMemberName] string? propertyName = null) where TSender : IReactiveObject { - reactiveObject.RaisingPropertyChanged(propertyName); + if (propertyName != null) + { + reactiveObject.RaisingPropertyChanged(propertyName); + } } /// @@ -157,10 +163,13 @@ public static void RaisePropertyChanged(this TSender reactiveObject, [C /// A string representing the name of the property that has been changed. /// Leave null to let the runtime set to caller member name. /// - public static void RaisePropertyChanging(this TSender reactiveObject, [CallerMemberName] string propertyName = null) + public static void RaisePropertyChanging(this TSender reactiveObject, [CallerMemberName] string? propertyName = null) where TSender : IReactiveObject { - reactiveObject.RaisingPropertyChanging(propertyName); + if (propertyName != null) + { + reactiveObject.RaisingPropertyChanging(propertyName); + } } internal static IObservable> GetChangedObservable(this TSender reactiveObject) @@ -195,7 +204,10 @@ internal static void SubscribePropertyChangingEvents(this TSender react internal static void RaisingPropertyChanging(this TSender reactiveObject, string propertyName) where TSender : IReactiveObject { - Contract.Requires(propertyName != null); + if (propertyName == null) + { + throw new ArgumentNullException(nameof(propertyName)); + } var s = state.GetValue(reactiveObject, _ => (IExtensionState)new ExtensionState(reactiveObject)); @@ -213,7 +225,10 @@ internal static void SubscribePropertyChangedEvents(this TSender reacti internal static void RaisingPropertyChanged(this TSender reactiveObject, string propertyName) where TSender : IReactiveObject { - Contract.Requires(propertyName != null); + if (propertyName == null) + { + throw new ArgumentNullException(nameof(propertyName)); + } var s = state.GetValue(reactiveObject, _ => (IExtensionState)new ExtensionState(reactiveObject)); @@ -380,11 +395,11 @@ public void RaisePropertyChanged(string propertyName) } } - internal void NotifyObservable(TSender rxObj, T item, ISubject subject) + internal void NotifyObservable(TSender rxObj, T item, ISubject? subject) { try { - subject.OnNext(item); + subject?.OnNext(item); } catch (Exception ex) { diff --git a/src/ReactiveUI/ReactiveObject/ReactiveObject.cs b/src/ReactiveUI/ReactiveObject/ReactiveObject.cs index e68c037f20..49a4d7001a 100644 --- a/src/ReactiveUI/ReactiveObject/ReactiveObject.cs +++ b/src/ReactiveUI/ReactiveObject/ReactiveObject.cs @@ -70,9 +70,9 @@ public event PropertyChangedEventHandler PropertyChanged remove => PropertyChangedHandler -= value; } - private event PropertyChangingEventHandler PropertyChangingHandler; + private event PropertyChangingEventHandler? PropertyChangingHandler; - private event PropertyChangedEventHandler PropertyChangedHandler; + private event PropertyChangedEventHandler? PropertyChangedHandler; /// [IgnoreDataMember] diff --git a/src/ReactiveUI/ReactiveUI.csproj b/src/ReactiveUI/ReactiveUI.csproj index 3b44d9713f..ff4b09d431 100644 --- a/src/ReactiveUI/ReactiveUI.csproj +++ b/src/ReactiveUI/ReactiveUI.csproj @@ -6,6 +6,7 @@ ReactiveUI A MVVM framework that integrates with the Reactive Extensions for .NET to create elegant, testable User Interfaces that run on any mobile or desktop platform. This is the base package with the base platform implementations ReactiveUI + enable latest diff --git a/src/ReactiveUI/Routing/MessageBus.cs b/src/ReactiveUI/Routing/MessageBus.cs index 3f8bfbc53f..f476f196ab 100644 --- a/src/ReactiveUI/Routing/MessageBus.cs +++ b/src/ReactiveUI/Routing/MessageBus.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -25,11 +26,11 @@ namespace ReactiveUI /// public class MessageBus : IMessageBus { - private readonly Dictionary<(Type type, string contract), NotAWeakReference> _messageBus = - new Dictionary<(Type type, string contract), NotAWeakReference>(); + private readonly Dictionary<(Type type, string? contract), NotAWeakReference> _messageBus = + new Dictionary<(Type type, string? contract), NotAWeakReference>(); - private readonly IDictionary<(Type type, string contract), IScheduler> _schedulerMappings = - new Dictionary<(Type type, string contract), IScheduler>(); + private readonly IDictionary<(Type type, string? contract), IScheduler> _schedulerMappings = + new Dictionary<(Type type, string? contract), IScheduler>(); /// /// Gets or sets the Current MessageBus. @@ -46,7 +47,7 @@ public class MessageBus : IMessageBus /// A unique string to distinguish messages with /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. - public void RegisterScheduler(IScheduler scheduler, string contract = null) + public void RegisterScheduler(IScheduler scheduler, string? contract = null) { _schedulerMappings[(typeof(T), contract)] = scheduler; } @@ -61,7 +62,7 @@ public void RegisterScheduler(IScheduler scheduler, string contract = null) /// only used for one purpose, leave this as null. /// An Observable representing the notifications posted to the /// message bus. - public IObservable Listen(string contract = null) + public IObservable Listen(string? contract = null) { this.Log().Info(CultureInfo.InvariantCulture, "Listening to {0}:{1}", typeof(T), contract); @@ -78,11 +79,11 @@ public IObservable Listen(string contract = null) /// only used for one purpose, leave this as null. /// An Observable representing the notifications posted to the /// message bus. - public IObservable ListenIncludeLatest(string contract = null) + public IObservable ListenIncludeLatest(string? contract = null) { this.Log().Info(CultureInfo.InvariantCulture, "Listening to {0}:{1}", typeof(T), contract); - return SetupSubjectIfNecessary(contract); + return SetupSubjectIfNecessary(contract) ?? Observable.Create(observer => observer.OnCompleted); } /// @@ -93,7 +94,7 @@ public IObservable ListenIncludeLatest(string contract = null) /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. /// True if messages have been posted for this message Type. - public bool IsRegistered(Type type, string contract = null) + public bool IsRegistered(Type type, string? contract = null) { bool ret = false; WithMessageBus(type, contract, (mb, item) => { ret = mb.ContainsKey(item) && mb[item].IsAlive; }); @@ -115,14 +116,14 @@ public bool IsRegistered(Type type, string contract = null) /// a Disposable. public IDisposable RegisterMessageSource( IObservable source, - string contract = null) + string? contract = null) { if (source == null) { throw new ArgumentNullException(nameof(source)); } - return source.Subscribe(SetupSubjectIfNecessary(contract)); + return source.Subscribe(SetupSubjectIfNecessary(contract) !); } /// @@ -136,24 +137,24 @@ public IDisposable RegisterMessageSource( /// A unique string to distinguish messages with /// identical types (i.e. "MyCoolViewModel") - if the message type is /// only used for one purpose, leave this as null. - public void SendMessage(T message, string contract = null) + public void SendMessage(T message, string? contract = null) { - SetupSubjectIfNecessary(contract).OnNext(message); + SetupSubjectIfNecessary(contract)?.OnNext(message); } - private ISubject SetupSubjectIfNecessary(string contract) + private ISubject? SetupSubjectIfNecessary(string? contract) { - ISubject ret = null; + ISubject? ret = null; WithMessageBus(typeof(T), contract, (mb, item) => { - if (mb.TryGetValue(item, out NotAWeakReference subjRef) && subjRef.IsAlive) + if (mb.TryGetValue(item, out NotAWeakReference? subjRef) && subjRef.IsAlive) { ret = (ISubject)subjRef.Target; return; } - ret = new ScheduledSubject(GetScheduler(item), null, new BehaviorSubject(default(T))); + ret = new ScheduledSubject(GetScheduler(item), null, new BehaviorSubject(default!)); mb[item] = new NotAWeakReference(ret); }); @@ -162,8 +163,8 @@ private ISubject SetupSubjectIfNecessary(string contract) private void WithMessageBus( Type type, - string contract, - Action, (Type type, string contract)> block) + string? contract, + Action, (Type type, string? contract)> block) { lock (_messageBus) { @@ -176,9 +177,9 @@ private void WithMessageBus( } } - private IScheduler GetScheduler((Type type, string contract) item) + private IScheduler GetScheduler((Type type, string? contract) item) { - _schedulerMappings.TryGetValue(item, out IScheduler scheduler); + _schedulerMappings.TryGetValue(item, out IScheduler? scheduler); return scheduler ?? CurrentThreadScheduler.Instance; } } diff --git a/src/ReactiveUI/Routing/RoutableViewModelMixin.cs b/src/ReactiveUI/Routing/RoutableViewModelMixin.cs index 9f907a8543..b05e47eab6 100644 --- a/src/ReactiveUI/Routing/RoutableViewModelMixin.cs +++ b/src/ReactiveUI/Routing/RoutableViewModelMixin.cs @@ -37,10 +37,10 @@ public static IDisposable WhenNavigatedTo(this IRoutableViewModel item, Func { if (router.GetCurrentViewModel() == item) @@ -80,13 +80,13 @@ public static IObservable WhenNavigatedToObservable(this IRoutableViewMode } var router = item.HostScreen.Router; - var navigationStackChanged = router.NavigationChanged.CountChanged(); + var navigationStackChanged = router.NavigationChanged?.CountChanged(); var itemRemoved = navigationStackChanged .Where(x => x.Any(change => change.Reason == ListChangeReason.Remove && change.Item.Current == item)); return navigationStackChanged - .Where(_ => router.GetCurrentViewModel() == item) + .Where(_ => router?.GetCurrentViewModel() == item) .Select(_ => Unit.Default) .TakeUntil(itemRemoved); } @@ -114,7 +114,7 @@ public static IObservable WhenNavigatingFromObservable(this IRoutableViewM } var router = item.HostScreen.Router; - var navigationStackChanged = router.NavigationChanged.CountChanged(); + var navigationStackChanged = router.NavigationChanged?.CountChanged(); bool StackIsCleared(Change change) => change.Reason == ListChangeReason.Clear; bool ThisViewModelIsRemoved(Change change) => NavigationStackRemovalOperations.Contains(change.Reason) && change.Item.Current == item; var itemRemoved = navigationStackChanged.Where(x => x.Any(change => StackIsCleared(change) || ThisViewModelIsRemoved(change))); diff --git a/src/ReactiveUI/Routing/RoutingState.cs b/src/ReactiveUI/Routing/RoutingState.cs index a4b2e06c38..6793ae1229 100644 --- a/src/ReactiveUI/Routing/RoutingState.cs +++ b/src/ReactiveUI/Routing/RoutingState.cs @@ -5,6 +5,7 @@ using System; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reactive; using System.Reactive.Concurrency; @@ -12,6 +13,7 @@ using System.Runtime.Serialization; using DynamicData; using DynamicData.Binding; +#pragma warning disable 8618 namespace ReactiveUI { @@ -19,6 +21,7 @@ namespace ReactiveUI /// RoutingState manages the ViewModel Stack and allows ViewModels to /// navigate to other ViewModels. /// + [SuppressMessage("Usage", "CS8618: Non-nullable property is uninitialized", Justification = "Searialization restores values.")] [DataContract] public class RoutingState : ReactiveObject { @@ -30,7 +33,7 @@ public class RoutingState : ReactiveObject /// /// Initializes static members of the class. - /// + /// R static RoutingState() { RxApp.EnsureInitialized(); @@ -50,8 +53,8 @@ public RoutingState() /// A scheduler for where to send navigation changes to. public RoutingState(IScheduler scheduler) { + _scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler)); _navigationStack = new ObservableCollection(); - _scheduler = scheduler; SetupRx(); } @@ -86,7 +89,7 @@ public IScheduler Scheduler public ReactiveCommand NavigateBack { get; protected set; } /// - /// Gets or sets a comamnd that navigates to the a new element in the stack - the Execute parameter + /// Gets or sets a command that navigates to the a new element in the stack - the Execute parameter /// must be a ViewModel that implements IRoutableViewModel. /// [IgnoreDataMember] @@ -131,32 +134,32 @@ private void SetupRx() NavigateBack = ReactiveCommand.CreateFromObservable( () => - { - _navigationStack.RemoveAt(NavigationStack.Count - 1); - return Observables.Unit; - }, + { + _navigationStack.RemoveAt(NavigationStack.Count - 1); + return Observables.Unit; + }, countAsBehavior.Select(x => x > 1), navigateScheduler); Navigate = ReactiveCommand.CreateFromObservable( vm => - { - if (vm == null) { - throw new Exception("Navigate must be called on an IRoutableViewModel"); - } + if (vm == null) + { + throw new Exception("Navigate must be called on an IRoutableViewModel"); + } - _navigationStack.Add(vm); - return Observable.Return(vm); - }, + _navigationStack.Add(vm); + return Observable.Return(vm); + }, outputScheduler: navigateScheduler); NavigateAndReset = ReactiveCommand.CreateFromObservable( vm => - { - _navigationStack.Clear(); - return Navigate.Execute(vm); - }, + { + _navigationStack.Clear(); + return Navigate.Execute(vm); + }, outputScheduler: navigateScheduler); CurrentViewModel = Observable.Defer(() => Observable.Return(NavigationStack.LastOrDefault())).Concat(NavigationChanged.Select(_ => NavigationStack.LastOrDefault())); diff --git a/src/ReactiveUI/RxApp.cs b/src/ReactiveUI/RxApp.cs index 335f42bd7f..bb7e1286c7 100644 --- a/src/ReactiveUI/RxApp.cs +++ b/src/ReactiveUI/RxApp.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reactive; using System.Reactive.Concurrency; using System.Runtime.CompilerServices; @@ -31,6 +32,7 @@ namespace ReactiveUI /// This class also initializes a whole bunch of other stuff, including the IoC container, /// logging and error handling. /// + [SuppressMessage("Usage", "CS8618: Non-nullable property is uninitialized", Justification = "Threading magic.")] public static class RxApp { #if ANDROID || IOS @@ -56,15 +58,15 @@ public static class RxApp #endif [ThreadStatic] - private static IScheduler _unitTestTaskpoolScheduler; - private static IScheduler _taskpoolScheduler; + private static IScheduler _unitTestTaskpoolScheduler = null!; + private static IScheduler _taskpoolScheduler = null!; [ThreadStatic] - private static IScheduler _unitTestMainThreadScheduler; - private static IScheduler _mainThreadScheduler; - private static IObserver _defaultExceptionHandler; + private static IScheduler _unitTestMainThreadScheduler = null!; + private static IScheduler _mainThreadScheduler = null!; + private static IObserver _defaultExceptionHandler = null!; [ThreadStatic] - private static ISuspensionHost _unitTestSuspensionHost; - private static ISuspensionHost _suspensionHost; + private static ISuspensionHost _unitTestSuspensionHost = null!; + private static ISuspensionHost _suspensionHost = null!; private static bool _hasSchedulerBeenChecked; /// @@ -152,7 +154,7 @@ public static IScheduler MainThreadScheduler LogHost.Default.Warn("You can install the needed package via NuGet, see https://reactiveui.net/docs/getting-started/installation/"); } - return _mainThreadScheduler; + return _mainThreadScheduler!; } set @@ -165,7 +167,7 @@ public static IScheduler MainThreadScheduler if (ModeDetector.InUnitTestRunner()) { _unitTestMainThreadScheduler = value; - _mainThreadScheduler = _mainThreadScheduler ?? value; + _mainThreadScheduler ??= value; } else { @@ -226,7 +228,7 @@ public static ISuspensionHost SuspensionHost if (ModeDetector.InUnitTestRunner()) { _unitTestSuspensionHost = value; - _suspensionHost = _suspensionHost ?? value; + _suspensionHost ??= value; } else { diff --git a/src/ReactiveUI/Scheduler/ScheduledSubject.cs b/src/ReactiveUI/Scheduler/ScheduledSubject.cs index 729493eb77..b1f8a66879 100644 --- a/src/ReactiveUI/Scheduler/ScheduledSubject.cs +++ b/src/ReactiveUI/Scheduler/ScheduledSubject.cs @@ -30,10 +30,10 @@ public class ScheduledSubject : ISubject, IDisposable /// The scheduler where to dispatch items to. /// A optional default observer where notifications will be sent. /// A optional default subject which this Subject will wrap. - public ScheduledSubject(IScheduler scheduler, IObserver defaultObserver = null, ISubject defaultSubject = null) + public ScheduledSubject(IScheduler scheduler, IObserver? defaultObserver = null, ISubject? defaultSubject = null) { _scheduler = scheduler; - _defaultObserver = defaultObserver; + _defaultObserver = defaultObserver ?? new Subject(); _subject = defaultSubject ?? new Subject(); if (defaultObserver != null) diff --git a/src/ReactiveUI/Scheduler/WaitForDispatcherScheduler.cs b/src/ReactiveUI/Scheduler/WaitForDispatcherScheduler.cs index 12e73d28cd..21b61e5778 100644 --- a/src/ReactiveUI/Scheduler/WaitForDispatcherScheduler.cs +++ b/src/ReactiveUI/Scheduler/WaitForDispatcherScheduler.cs @@ -17,7 +17,7 @@ namespace ReactiveUI public class WaitForDispatcherScheduler : IScheduler { private readonly Func _schedulerFactory; - private IScheduler _scheduler; + private IScheduler? _scheduler; /// /// Initializes a new instance of the class. diff --git a/src/ReactiveUI/Suspension/SuspensionHost.cs b/src/ReactiveUI/Suspension/SuspensionHost.cs index ab2d25af28..abcc19dd9f 100644 --- a/src/ReactiveUI/Suspension/SuspensionHost.cs +++ b/src/ReactiveUI/Suspension/SuspensionHost.cs @@ -28,7 +28,7 @@ internal class SuspensionHost : ReactiveObject, ISuspensionHost, IDisposable private readonly ReplaySubject> _shouldInvalidateState = new ReplaySubject>(1); - private object _appState; + private object? _appState; /// /// Initializes a new instance of the class. @@ -97,12 +97,12 @@ public IObservable ShouldInvalidateState /// /// Gets or sets a Func which will generate a fresh application state. /// - public Func CreateNewAppState { get; set; } + public Func? CreateNewAppState { get; set; } /// /// Gets or sets the application state that will be used when suspending and resuming the class. /// - public object AppState + public object? AppState { get => _appState; set => this.RaiseAndSetIfChanged(ref _appState, value); diff --git a/src/ReactiveUI/Suspension/SuspensionHostExtensions.cs b/src/ReactiveUI/Suspension/SuspensionHostExtensions.cs index 7caaa5c0a5..41c8e1c66e 100644 --- a/src/ReactiveUI/Suspension/SuspensionHostExtensions.cs +++ b/src/ReactiveUI/Suspension/SuspensionHostExtensions.cs @@ -24,7 +24,7 @@ public static class SuspensionHostExtensions public static IObservable ObserveAppState(this ISuspensionHost item) where T : class { - return item.WhenAny(x => x.AppState, x => (T)x.Value) + return item.WhenAny(x => x.AppState, x => (T)x) .Where(x => x != null); } @@ -41,6 +41,11 @@ public static T GetAppState(this ISuspensionHost item) throw new ArgumentNullException(nameof(item)); } + if (item.AppState == null) + { + throw new NullReferenceException(nameof(item.AppState)); + } + return (T)item.AppState; } @@ -51,15 +56,20 @@ public static T GetAppState(this ISuspensionHost item) /// The suspension host. /// The suspension driver. /// A disposable which will stop responding to Suspend and Resume requests. - public static IDisposable SetupDefaultSuspendResume(this ISuspensionHost item, ISuspensionDriver driver = null) + public static IDisposable SetupDefaultSuspendResume(this ISuspensionHost item, ISuspensionDriver? driver = null) { if (item == null) { throw new ArgumentNullException(nameof(item)); } + if (item.AppState == null) + { + throw new NullReferenceException(nameof(item.AppState)); + } + var ret = new CompositeDisposable(); - driver = driver ?? Locator.Current.GetService(); + driver ??= Locator.Current.GetService(); ret.Add(item.ShouldInvalidateState .SelectMany(_ => driver.InvalidateState()) @@ -75,9 +85,9 @@ public static IDisposable SetupDefaultSuspendResume(this ISuspensionHost item, I .SelectMany(x => driver.LoadState()) .LoggedCatch( item, - Observable.Defer(() => Observable.Return(item.CreateNewAppState())), + Observable.Defer(() => Observable.Return(item.CreateNewAppState?.Invoke())), "Failed to restore app state from storage, creating from scratch") - .Subscribe(x => item.AppState = x ?? item.CreateNewAppState())); + .Subscribe(x => item.AppState = x ?? item.CreateNewAppState?.Invoke())); return ret; } diff --git a/src/ReactiveUI/View/DefaultViewLocator.cs b/src/ReactiveUI/View/DefaultViewLocator.cs index 1508d1782f..7da4b65538 100644 --- a/src/ReactiveUI/View/DefaultViewLocator.cs +++ b/src/ReactiveUI/View/DefaultViewLocator.cs @@ -22,7 +22,7 @@ public sealed class DefaultViewLocator : IViewLocator, IEnableLogger /// /// The method which will convert a ViewModel name into a View. [SuppressMessage("Globalization", "CA1307: operator could change based on locale settings", Justification = "Replace() does not have third parameter on all platforms")] - internal DefaultViewLocator(Func viewModelToViewFunc = null) + internal DefaultViewLocator(Func? viewModelToViewFunc = null) { ViewModelToViewFunc = viewModelToViewFunc ?? (vm => vm.Replace("ViewModel", "View")); } @@ -93,8 +93,7 @@ internal DefaultViewLocator(Func viewModelToViewFunc = null) /// /// The view associated with the given view model. /// - public IViewFor ResolveView(T viewModel, string contract = null) - where T : class + public IViewFor? ResolveView(T viewModel, string? contract = null) { if (viewModel is null) { @@ -115,7 +114,7 @@ public IViewFor ResolveView(T viewModel, string contract = null) return view; } - view = AttemptViewResolutionFor(ToggleViewModelType(viewModel.GetType()), contract); + view = AttemptViewResolutionFor(ToggleViewModelType(viewModel?.GetType()), contract); if (view != null) { @@ -133,10 +132,20 @@ public IViewFor ResolveView(T viewModel, string contract = null) return null; } - private static Type ToggleViewModelType(Type viewModelType) + private static Type? ToggleViewModelType(Type? viewModelType) { + if (viewModelType == null) + { + return null; + } + var viewModelTypeName = viewModelType.AssemblyQualifiedName; + if (viewModelTypeName == null) + { + return null; + } + if (viewModelType.GetTypeInfo().IsInterface) { if (viewModelType.Name.StartsWith("I", StringComparison.InvariantCulture)) @@ -168,7 +177,7 @@ private static string InterfaceifyTypeName(string typeName) return typeName.Insert(idxPeriod + 1, "I"); } - private IViewFor AttemptViewResolutionFor(Type viewModelType, string contract) + private IViewFor? AttemptViewResolutionFor(Type? viewModelType, string? contract) { if (viewModelType == null) { @@ -176,6 +185,12 @@ private IViewFor AttemptViewResolutionFor(Type viewModelType, string contract) } var viewModelTypeName = viewModelType.AssemblyQualifiedName; + + if (viewModelTypeName == null) + { + return null; + } + var proposedViewTypeName = ViewModelToViewFunc(viewModelTypeName); var view = AttemptViewResolution(proposedViewTypeName, contract); @@ -195,7 +210,7 @@ private IViewFor AttemptViewResolutionFor(Type viewModelType, string contract) return null; } - private IViewFor AttemptViewResolution(string viewTypeName, string contract) + private IViewFor? AttemptViewResolution(string? viewTypeName, string? contract) { try {