Skip to content
Closed
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
8 changes: 4 additions & 4 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@

<!-- Versions: Directory.Packages.props (Central Package Management). PrivateAssets=all is implicit. -->
<ItemGroup>
<GlobalPackageReference Include="Microsoft.NETFramework.ReferenceAssemblies"
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies"
Condition=" $(UseMaui) != 'true' " />
<GlobalPackageReference Include="Nerdbank.GitVersioning"
<PackageReference Include="Nerdbank.GitVersioning"
Condition=" $(DISABLE_GITVERSIONING) != 'true' AND !$(MSBuildProjectDirectory.Contains('e2e')) " />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub"
<PackageReference Include="Microsoft.SourceLink.GitHub"
Condition=" $(IsPackable) " />
<GlobalPackageReference Include="Microsoft.Sbom.Targets"
<PackageReference Include="Microsoft.Sbom.Targets"
Condition=" $(IsPackable) " />
</ItemGroup>

Expand Down
4 changes: 2 additions & 2 deletions src/Prism.Core/Common/IParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ namespace Prism.Common
/// <summary>
/// Defines a contract for specifying values associated with a unique key.
/// </summary>
public interface IParameters : IEnumerable<KeyValuePair<string, object>>
public interface IParameters : IEnumerable<KeyValuePair<string, object?>>
{
/// <summary>
/// Adds the specified key and value to the parameter collection.
/// </summary>
/// <param name="key">The key of the parameter to add.</param>
/// <param name="value">The value of the parameter to add.</param>
void Add(string key, object value);
void Add(string key, object? value);

/// <summary>
/// Determines whether the <see cref="IParameters"/> contains the specified <paramref name="key"/>.
Expand Down
4 changes: 2 additions & 2 deletions src/Prism.Core/Common/ParametersBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public object? this[string key]
/// </summary>
/// <param name="key">The key to reference this value in the parameters collection.</param>
/// <param name="value">The value of the parameter to store.</param>
public void Add(string key, object value) =>
public void Add(string key, object? value) =>
_entries.Add(new KeyValuePair<string, object?>(key, value));

/// <summary>
Expand All @@ -129,7 +129,7 @@ public bool ContainsKey(string key) =>
/// <param name="key">The key for the value to be returned.</param>
/// <returns>Returns a matching parameter of <typeparamref name="T"/> if one exists in the Collection.</returns>
public T GetValue<T>(string key) =>
_entries.GetValue<T>(key);
_entries.GetValue<T>(key)!;

/// <summary>
/// Returns an IEnumerable of all parameters.
Expand Down
25 changes: 15 additions & 10 deletions src/Prism.Core/Common/ParametersExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ public static class ParametersExtensions
/// <param name="key">The key of the parameter to find</param>
/// <returns>A matching value of <typeparamref name="T"/> if it exists</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static T GetValue<T>(this IEnumerable<KeyValuePair<string, object>> parameters, string key) =>
(T)GetValue(parameters, key, typeof(T));
public static T GetValue<T>(this IEnumerable<KeyValuePair<string, object?>> parameters, string key)
{
object? value = GetValue(parameters, key, typeof(T));
if (value is null)
return default!;
return (T)value;
}

/// <summary>
/// Searches <paramref name="parameters"/> for value referenced by <paramref name="key"/>
Expand All @@ -33,7 +38,7 @@ public static T GetValue<T>(this IEnumerable<KeyValuePair<string, object>> param
/// <returns>A matching value of <paramref name="type"/> if it exists</returns>
/// <exception cref="InvalidCastException">Unable to convert the value of Type</exception>
[EditorBrowsable(EditorBrowsableState.Never)]
public static object GetValue(this IEnumerable<KeyValuePair<string, object>> parameters, string key, Type type)
public static object? GetValue(this IEnumerable<KeyValuePair<string, object?>> parameters, string key, Type type)
{
foreach (var kvp in parameters)
{
Expand All @@ -42,7 +47,7 @@ public static object GetValue(this IEnumerable<KeyValuePair<string, object>> par
if (TryGetValueInternal(kvp, type, out var value))
return value;

throw new InvalidCastException($"Unable to convert the value of Type '{kvp.Value.GetType().FullName}' to '{type.FullName}' for the key '{key}' ");
throw new InvalidCastException($"Unable to convert the value of Type '{kvp.Value!.GetType().FullName}' to '{type.FullName}' for the key '{key}' ");
}
}

Expand All @@ -58,7 +63,7 @@ public static object GetValue(this IEnumerable<KeyValuePair<string, object>> par
/// <param name="value">The value of parameter to return</param>
/// <returns>Success if value is found; otherwise returns <c>false</c></returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool TryGetValue<T>(this IEnumerable<KeyValuePair<string, object>> parameters, string key, out T value)
public static bool TryGetValue<T>(this IEnumerable<KeyValuePair<string, object?>> parameters, string key, [MaybeNullWhen(false)] out T value)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Return true for stored null parameter values

Because Add now explicitly accepts nullable values, callers can store an explicit null and should still be able to distinguish that from a missing key. This TryGetValue<T> path still only returns from the loop when valueAsObject is T, which is false for null, so TryGetValue<object?>("key", out _) or TryGetValue<string?>(...) reports false even though the key exists, contradicting the interface contract that the bool indicates whether the collection contains the key.

Useful? React with 👍 / 👎.

{
var type = typeof(T);

Expand All @@ -75,7 +80,7 @@ public static bool TryGetValue<T>(this IEnumerable<KeyValuePair<string, object>>
}
}

value = default;
value = default!;
return false;
}

Expand All @@ -87,7 +92,7 @@ public static bool TryGetValue<T>(this IEnumerable<KeyValuePair<string, object>>
/// <param name="key">The key of the parameter to find</param>
/// <returns>An IEnumerable{T} of all the values referenced by key</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable<T> GetValues<T>(this IEnumerable<KeyValuePair<string, object>> parameters, string key)
public static IEnumerable<T> GetValues<T>(this IEnumerable<KeyValuePair<string, object?>> parameters, string key)
{
List<T> values = [];
var type = typeof(T);
Expand All @@ -105,7 +110,7 @@ public static IEnumerable<T> GetValues<T>(this IEnumerable<KeyValuePair<string,
return values.ToArray();
}

private static bool TryGetValueInternal(KeyValuePair<string, object> kvp, Type type, out object value)
private static bool TryGetValueInternal(KeyValuePair<string, object?> kvp, Type type, out object? value)
{
value = GetDefault(type);
var valueAsString = kvp.Value is string str ? str : kvp.Value?.ToString();
Expand Down Expand Up @@ -141,7 +146,7 @@ private static bool TryGetValueInternal(KeyValuePair<string, object> kvp, Type t
if (!success && type.GetInterface("System.IConvertible") != null)
{
success = true;
value = Convert.ChangeType(kvp.Value, type);
value = Convert.ChangeType(kvp.Value, type)!;
}

return success;
Expand All @@ -154,7 +159,7 @@ private static bool TryGetValueInternal(KeyValuePair<string, object> kvp, Type t
/// <param name="key">The key to search the <paramref name="parameters"/> for existence</param>
/// <returns><c>true</c> if key exists; <c>false</c> otherwise</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public static bool ContainsKey(this IEnumerable<KeyValuePair<string, object>> parameters, string key) =>
public static bool ContainsKey(this IEnumerable<KeyValuePair<string, object?>> parameters, string key) =>
parameters.Any(x => string.Compare(x.Key, key, StringComparison.Ordinal) == 0);

private static object? GetDefault(Type type) => type.IsValueType ? Activator.CreateInstance(type) : null;
Expand Down
4 changes: 2 additions & 2 deletions src/Prism.Core/Common/UriParsingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public static INavigationParameters GetSegmentParameters(string uriSegment, INav

if (parameters is not null)
{
foreach (KeyValuePair<string, object> navigationParameter in parameters)
foreach (KeyValuePair<string, object?> navigationParameter in parameters)
{
navParameters.Add(navigationParameter.Key, navigationParameter.Value);
}
Expand Down Expand Up @@ -116,7 +116,7 @@ public static IDialogParameters GetSegmentParameters(string uriSegment, IDialogP

if (parameters != null)
{
foreach (KeyValuePair<string, object> navigationParameter in parameters)
foreach (KeyValuePair<string, object?> navigationParameter in parameters)
{
dialogParameters.Add(navigationParameter.Key, navigationParameter.Value);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#if NETFRAMEWORK

using System;
using System.Runtime.Serialization;
Expand All @@ -17,3 +17,5 @@ public partial class CyclicDependencyFoundException
protected CyclicDependencyFoundException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#if NETFRAMEWORK

using System;
using System.Runtime.Serialization;
Expand All @@ -17,3 +17,5 @@ public partial class DuplicateModuleException
protected DuplicateModuleException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

#endif
6 changes: 3 additions & 3 deletions src/Prism.Core/Modularity/ModularityException.Desktop.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#if NETFRAMEWORK

using System;
using System.Runtime.Serialization;
Expand All @@ -25,13 +25,13 @@ protected ModularityException(SerializationInfo info, StreamingContext context)
/// </summary>
/// <param name="info">The <see cref="System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
#if !NET6_0_OR_GREATER
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.SerializationFormatter)]
#endif
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("ModuleName", this.ModuleName);
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#if NETFRAMEWORK

using System;
using System.Runtime.Serialization;
Expand All @@ -19,3 +19,5 @@ protected ModuleInitializeException(SerializationInfo info, StreamingContext con
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#if NETFRAMEWORK

using System;
using System.Runtime.Serialization;
Expand All @@ -22,3 +22,5 @@ protected ModuleNotFoundException(SerializationInfo info, StreamingContext conte
}
}
}

#endif
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#if NETFRAMEWORK

using System;
using System.Runtime.Serialization;
Expand All @@ -19,3 +19,5 @@ protected ModuleTypeLoadingException(SerializationInfo info, StreamingContext co
}
}
}

#endif
36 changes: 17 additions & 19 deletions src/Prism.Core/Mvvm/ErrorsContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Prism.Mvvm
/// <typeparam name="T">The type of the error object.</typeparam>
public class ErrorsContainer<T>
{
private static readonly T[] noErrors = new T[0];
private static readonly T[] noErrors = [];

/// <summary>
/// Delegate to be called when raiseErrorsChanged is invoked.
Expand All @@ -27,25 +27,23 @@ public class ErrorsContainer<T>
/// <param name="raiseErrorsChanged">The action that is invoked when errors are added for an object.</param>
public ErrorsContainer(Action<string> raiseErrorsChanged)
{
#if NETFRAMEWORK
if (raiseErrorsChanged == null)
{
throw new ArgumentNullException(nameof(raiseErrorsChanged));
}
#else
ArgumentNullException.ThrowIfNull(raiseErrorsChanged);
#endif

this.raiseErrorsChanged = raiseErrorsChanged;
this.validationResults = new Dictionary<string, List<T>>();
validationResults = [];
}

/// <summary>
/// Gets a value indicating whether the object has validation errors.
/// </summary>
public bool HasErrors
{
get
{
return this.validationResults.Count != 0;
}
}
public bool HasErrors => validationResults.Count != 0;

/// <summary>
/// Returns all the errors in the container.
Expand All @@ -61,7 +59,7 @@ public bool HasErrors
public IEnumerable<T> GetErrors(string? propertyName)
{
var localPropertyName = propertyName ?? string.Empty;
if (this.validationResults.TryGetValue(localPropertyName, out var currentValidationResults))
if (validationResults.TryGetValue(localPropertyName, out var currentValidationResults))
{
return currentValidationResults;
}
Expand All @@ -76,7 +74,7 @@ public IEnumerable<T> GetErrors(string? propertyName)
/// </summary>
public void ClearErrors()
{
foreach (var key in this.validationResults.Keys.ToArray())
foreach (var key in validationResults.Keys.ToArray())
{
ClearErrors(key);
}
Expand All @@ -94,7 +92,7 @@ public void ClearErrors()
public void ClearErrors<TProperty>(Expression<Func<TProperty>> propertyExpression)
{
var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
this.ClearErrors(propertyName);
ClearErrors(propertyName);
}

/// <summary>
Expand All @@ -104,7 +102,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) => SetErrors(propertyName, new List<T>());

/// <summary>
/// Sets the validation errors for the specified property.
Expand All @@ -116,7 +114,7 @@ public void ClearErrors<TProperty>(Expression<Func<TProperty>> propertyExpressio
public void SetErrors<TProperty>(Expression<Func<TProperty>> propertyExpression, IEnumerable<T>? propertyErrors)
{
var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
this.SetErrors(propertyName, propertyErrors);
SetErrors(propertyName, propertyErrors);
}

/// <summary>
Expand All @@ -130,20 +128,20 @@ public void SetErrors<TProperty>(Expression<Func<TProperty>> propertyExpression,
public void SetErrors(string? propertyName, IEnumerable<T>? newValidationResults)
{
var localPropertyName = propertyName ?? string.Empty;
var hasCurrentValidationResults = this.validationResults.ContainsKey(localPropertyName);
var hasCurrentValidationResults = validationResults.ContainsKey(localPropertyName);
var hasNewValidationResults = newValidationResults != null && newValidationResults.Count() > 0;

if (hasCurrentValidationResults || hasNewValidationResults)
{
if (hasNewValidationResults)
{
this.validationResults[localPropertyName] = new List<T>(newValidationResults);
this.raiseErrorsChanged(localPropertyName);
validationResults[localPropertyName] = new List<T>(newValidationResults!);
raiseErrorsChanged(localPropertyName);
}
else
{
this.validationResults.Remove(localPropertyName);
this.raiseErrorsChanged(localPropertyName);
validationResults.Remove(localPropertyName);
raiseErrorsChanged(localPropertyName);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Prism.Core/Mvvm/PropertySupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static class PropertySupport
throw new ArgumentException(Resources.PropertySupport_ExpressionNotProperty_Exception, nameof(expression));

var getMethod = property.GetMethod;
if (getMethod.IsStatic)
if (getMethod is null || getMethod.IsStatic)
throw new ArgumentException(Resources.PropertySupport_StaticExpression_Exception, nameof(expression));

return memberExpression.Member.Name;
Expand Down
4 changes: 2 additions & 2 deletions src/Prism.Core/Mvvm/ViewModelLocationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static void Reset()
{
_factories = new Dictionary<string, Func<object>>();
_typeFactories = new Dictionary<string, Type>();
_defaultViewModelFactory = type => Activator.CreateInstance(type);
_defaultViewModelFactory = type => Activator.CreateInstance(type)!;
_defaultViewModelFactoryWithViewParameter = null;
_defaultViewTypeToViewModelTypeResolver = DefaultViewTypeToViewModel;
}
Expand All @@ -44,7 +44,7 @@ public static void Reset()
/// <summary>
/// The default view model factory which provides the ViewModel type as a parameter.
/// </summary>
static Func<Type, object> _defaultViewModelFactory = type => Activator.CreateInstance(type);
static Func<Type, object> _defaultViewModelFactory = type => Activator.CreateInstance(type)!;

/// <summary>
/// ViewModelFactory that provides the View instance and ViewModel type as parameters.
Expand Down
3 changes: 2 additions & 1 deletion src/Prism.Core/Mvvm/ViewRegistryBase{TBaseView}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ private IEnumerable<Type> GetCandidates(Type viewModelType)

return candidates
.Select(x => Type.GetType(x, false))
.Where(x => x is not null);
.Where(x => x is not null)
.Cast<Type>();
}

return [];
Expand Down
Loading
Loading