Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: enable nullability for core mvvm #3140

Merged
merged 2 commits into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/Prism.Core/Mvvm/BindableBase.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;

#nullable enable
namespace Prism.Mvvm
{
/// <summary>
Expand All @@ -13,7 +12,7 @@ public abstract class BindableBase : INotifyPropertyChanged
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;

/// <summary>
/// Checks if a property already matches a desired value. Sets the property and
Expand All @@ -27,7 +26,7 @@ public abstract class BindableBase : INotifyPropertyChanged
/// support CallerMemberName.</param>
/// <returns>True if the value was changed, false if the existing value matched the
/// desired value.</returns>
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;

Expand All @@ -50,7 +49,8 @@ protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName]
/// <param name="onChanged">Action that is called after the property value has been changed.</param>
/// <returns>True if the value was changed, false if the existing value matched the
/// desired value.</returns>
protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
protected virtual bool SetProperty<T>(ref T storage, T value, Action? onChanged,
[CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;

Expand All @@ -67,7 +67,7 @@ protected virtual bool SetProperty<T>(ref T storage, T value, Action onChanged,
/// <param name="propertyName">Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers
/// that support <see cref="CallerMemberNameAttribute"/>.</param>
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
protected void RaisePropertyChanged([CallerMemberName] string? propertyName = null)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
Expand Down
23 changes: 7 additions & 16 deletions src/Prism.Core/Mvvm/ErrorsContainer.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

#nullable enable
namespace Prism.Mvvm
{
/// <summary>
Expand Down Expand Up @@ -53,21 +51,17 @@ public bool HasErrors
/// Returns all the errors in the container.
/// </summary>
/// <returns>The dictionary of errors per property.</returns>
public Dictionary<string, List<T>> GetErrors()
{
return validationResults;
}
public Dictionary<string, List<T>> GetErrors() => validationResults;

/// <summary>
/// Gets the validation errors for a specified property.
/// </summary>
/// <param name="propertyName">The name of the property.</param>
/// <returns>The validation errors of type <typeparamref name="T"/> for the property.</returns>
public IEnumerable<T> GetErrors(string propertyName)
public IEnumerable<T> GetErrors(string? propertyName)
{
var localPropertyName = propertyName ?? string.Empty;
List<T> currentValidationResults = null;
if (this.validationResults.TryGetValue(localPropertyName, out currentValidationResults))
if (this.validationResults.TryGetValue(localPropertyName, out var currentValidationResults))
{
return currentValidationResults;
}
Expand Down Expand Up @@ -110,10 +104,7 @@ public void ClearErrors<TProperty>(Expression<Func<TProperty>> propertyExpressio
/// <example>
/// container.ClearErrors("SomeProperty");
/// </example>
public void ClearErrors(string propertyName)
{
this.SetErrors(propertyName, new List<T>());
}
public void ClearErrors(string? propertyName) => this.SetErrors(propertyName, new List<T>());

/// <summary>
/// Sets the validation errors for the specified property.
Expand All @@ -122,7 +113,7 @@ public void ClearErrors(string propertyName)
/// <param name="propertyExpression">The <see cref="Expression"/> indicating the property.</param>
/// <param name="propertyErrors">The list of errors to set for the property.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
public void SetErrors<TProperty>(Expression<Func<TProperty>> propertyExpression, IEnumerable<T> propertyErrors)
public void SetErrors<TProperty>(Expression<Func<TProperty>> propertyExpression, IEnumerable<T>? propertyErrors)
{
var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
this.SetErrors(propertyName, propertyErrors);
Expand All @@ -136,7 +127,7 @@ public void SetErrors<TProperty>(Expression<Func<TProperty>> propertyExpression,
/// </remarks>
/// <param name="propertyName">The name of the property.</param>
/// <param name="newValidationResults">The new validation errors.</param>
public void SetErrors(string propertyName, IEnumerable<T> newValidationResults)
public void SetErrors(string? propertyName, IEnumerable<T>? newValidationResults)
{
var localPropertyName = propertyName ?? string.Empty;
var hasCurrentValidationResults = this.validationResults.ContainsKey(localPropertyName);
Expand Down
6 changes: 1 addition & 5 deletions src/Prism.Core/Mvvm/IViewRegistry.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using Prism.Ioc;

namespace Prism.Mvvm;
namespace Prism.Mvvm;

/// <summary>
/// Provides an abstraction layer for ViewRegistration that can be mocked
Expand Down
8 changes: 3 additions & 5 deletions src/Prism.Core/Mvvm/PropertySupport.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@


using System;
using System.Linq.Expressions;
using System.Reflection;
using Prism.Properties;

#nullable enable
namespace Prism.Mvvm
{
///<summary>
Expand All @@ -24,7 +22,7 @@ public static class PropertySupport
/// The <see cref="MemberExpression"/> does not represent a property.<br/>
/// Or, the property is static.
/// </exception>
public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
public static string? ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression == null)
throw new ArgumentNullException(nameof(propertyExpression));
Expand All @@ -42,7 +40,7 @@ public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpressi
/// The <see cref="MemberExpression"/> does not represent a property.<br/>
/// Or, the property is static.
/// </exception>
internal static string ExtractPropertyNameFromLambda(LambdaExpression expression)
internal static string? ExtractPropertyNameFromLambda(LambdaExpression expression)
{
if (expression == null)
throw new ArgumentNullException(nameof(expression));
Expand Down
5 changes: 2 additions & 3 deletions src/Prism.Core/Mvvm/ViewCreationException.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;

#nullable enable
namespace Prism.Mvvm;

/// <summary>
Expand All @@ -23,7 +22,7 @@ public ViewCreationException(string viewName, ViewType viewType)
/// <param name="viewName">The name of the view that failed to create.</param>
/// <param name="viewType">The type of view that failed to create (Page, Region, or Dialog).</param>
/// <param name="innerException">The inner exception that caused the view creation to fail.</param>
public ViewCreationException(string viewName, ViewType viewType, Exception innerException)
public ViewCreationException(string viewName, ViewType viewType, Exception? innerException)
: base($"Unable to create {viewType} '{viewName}'.", innerException)
{
ViewName = viewName;
Expand Down
6 changes: 3 additions & 3 deletions src/Prism.Core/Mvvm/ViewModelCreationException.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using System;
using System.ComponentModel;
using System.ComponentModel;

#nullable enable
namespace Prism.Mvvm;

/// <summary>
/// Exception thrown when an error occurs during ViewModel creation.
/// </summary>
public class ViewModelCreationException : Exception
{
private static Func<object, string> _viewNameDelegate = null;
private static Func<object, string>? _viewNameDelegate;

/// <summary>
/// Gets the name of the view associated with the exception, based on platform-specific logic.
Expand Down
37 changes: 14 additions & 23 deletions src/Prism.Core/Mvvm/ViewModelLocationProvider.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection;

#nullable enable
namespace Prism.Mvvm
{
/// <summary>
Expand Down Expand Up @@ -52,24 +49,24 @@ public static void Reset()
/// <summary>
/// ViewModelFactory that provides the View instance and ViewModel type as parameters.
/// </summary>
static Func<object, Type, object> _defaultViewModelFactoryWithViewParameter;
static Func<object, Type, object>? _defaultViewModelFactoryWithViewParameter;

/// <summary>
/// Default view type to view model type resolver, assumes the view model is in same assembly as the view type, but in the "ViewModels" namespace.
/// </summary>
static Func<Type, Type> _defaultViewTypeToViewModelTypeResolver = DefaultViewTypeToViewModel;
static Func<Type, Type?> _defaultViewTypeToViewModelTypeResolver = DefaultViewTypeToViewModel;

private static Type DefaultViewTypeToViewModel(Type viewType)
private static Type? DefaultViewTypeToViewModel(Type viewType)
{
var viewName = viewType.FullName;
viewName = viewName.Replace(".Views.", ".ViewModels.");
viewName = viewName?.Replace(".Views.", ".ViewModels.");
var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;
var suffix = viewName.EndsWith("View") ? "Model" : "ViewModel";
var suffix = viewName != null && viewName.EndsWith("View") ? "Model" : "ViewModel";
var viewModelName = string.Format(CultureInfo.InvariantCulture, "{0}{1}, {2}", viewName, suffix, viewAssemblyName);
return Type.GetType(viewModelName);
}

static Func<object, Type> _defaultViewToViewModelTypeResolver = view => null;
static Func<object, Type?> _defaultViewToViewModelTypeResolver = view => null;

/// <summary>
/// Sets the default view model factory.
Expand All @@ -93,7 +90,7 @@ public static void SetDefaultViewModelFactory(Func<object, Type, object> viewMod
/// Sets the default view type to view model type resolver.
/// </summary>
/// <param name="viewTypeToViewModelTypeResolver">The view type to view model type resolver.</param>
public static void SetDefaultViewTypeToViewModelTypeResolver(Func<Type, Type> viewTypeToViewModelTypeResolver)
public static void SetDefaultViewTypeToViewModelTypeResolver(Func<Type, Type?> viewTypeToViewModelTypeResolver)
{
_defaultViewTypeToViewModelTypeResolver = viewTypeToViewModelTypeResolver;
}
Expand All @@ -102,7 +99,7 @@ public static void SetDefaultViewTypeToViewModelTypeResolver(Func<Type, Type> vi
/// Sets the default ViewModel Type Resolver given the View instance. This can be used to evaluate the View for
/// custom attributes or Attached Properties to determine the ViewModel Type.
/// </summary>
public static void SetDefaultViewToViewModelTypeResolver(Func<object, Type> viewToViewModelTypeResolver) =>
public static void SetDefaultViewToViewModelTypeResolver(Func<object, Type?> viewToViewModelTypeResolver) =>
_defaultViewToViewModelTypeResolver = viewToViewModelTypeResolver;

/// <summary>
Expand All @@ -114,7 +111,7 @@ public static void SetDefaultViewToViewModelTypeResolver(Func<object, Type> view
public static void AutoWireViewModelChanged(object view, Action<object, object> setDataContextCallback)
{
// Try mappings first
object viewModel = GetViewModelForView(view);
object? viewModel = GetViewModelForView(view);

// try to use ViewModel type
if (viewModel == null)
Expand Down Expand Up @@ -144,30 +141,24 @@ public static void AutoWireViewModelChanged(object view, Action<object, object>
/// </summary>
/// <param name="view">The view that the view model wants.</param>
/// <returns>The ViewModel that corresponds to the view passed as a parameter.</returns>
private static object GetViewModelForView(object view)
private static object? GetViewModelForView(object view)
{
var viewKey = view.GetType().ToString();

// Mapping of view models base on view type (or instance) goes here
if (_factories.ContainsKey(viewKey))
return _factories[viewKey]();

return null;
return _factories.ContainsKey(viewKey) ? _factories[viewKey]() : null;
}

/// <summary>
/// Gets the ViewModel type for the specified view.
/// </summary>
/// <param name="view">The View that the ViewModel wants.</param>
/// <returns>The ViewModel type that corresponds to the View.</returns>
private static Type GetViewModelTypeForView(Type view)
private static Type? GetViewModelTypeForView(Type view)
{
var viewKey = view.ToString();

if (_typeFactories.ContainsKey(viewKey))
return _typeFactories[viewKey];

return null;
return _typeFactories.ContainsKey(viewKey) ? _typeFactories[viewKey] : null;
}

/// <summary>
Expand Down
4 changes: 1 addition & 3 deletions src/Prism.Core/Mvvm/ViewRegistration.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;

namespace Prism.Mvvm;
namespace Prism.Mvvm;

/// <summary>
/// Represents information about a registered view.
Expand Down
Loading
Loading