Skip to content

Commit

Permalink
Merge pull request #3140 from RLittlesII/chore/nullability/mvvm
Browse files Browse the repository at this point in the history
chore: enable nullability for core mvvm
  • Loading branch information
dansiegel authored May 25, 2024
2 parents fd8b659 + 1ce4c73 commit e296a0a
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 108 deletions.
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

0 comments on commit e296a0a

Please sign in to comment.