Skip to content

Commit

Permalink
Resolve nullable warnings (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
chullybun authored Apr 17, 2024
1 parent dd5cdd5 commit e5b0ee0
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 12 deletions.
5 changes: 2 additions & 3 deletions src/CoreEx.Validation/Rules/ReferenceDataSidListRule.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx

using CoreEx.RefData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
Expand All @@ -12,7 +11,7 @@ namespace CoreEx.Validation.Rules
/// <summary>
/// Provides validation for a <see cref="IReferenceDataCodeList"/> including <see cref="MinCount"/>, <see cref="MaxCount"/>, per item <see cref="IReferenceData.IsValid"/>, and whether to <see cref="AllowDuplicates"/>.
/// </summary>
public class ReferenceDataSidListRule<TEntity, TProperty> : ValueRuleBase<TEntity, TProperty?> where TEntity : class where TProperty : IReferenceDataCodeList
public class ReferenceDataSidListRule<TEntity, TProperty> : ValueRuleBase<TEntity, TProperty> where TEntity : class where TProperty : IReferenceDataCodeList?
{
/// <summary>
/// Initializes a new instance of the <see cref="ReferenceDataSidListRule{TEntity, TProperty}"/> class.
Expand All @@ -35,7 +34,7 @@ public class ReferenceDataSidListRule<TEntity, TProperty> : ValueRuleBase<TEntit
public bool AllowDuplicates { get; set; } = false;

/// <inheritdoc/>
protected override Task ValidateAsync(PropertyContext<TEntity, TProperty?> context, CancellationToken cancellationToken = default)
protected override Task ValidateAsync(PropertyContext<TEntity, TProperty> context, CancellationToken cancellationToken = default)
{
if (context.Value!.HasInvalidItems)
{
Expand Down
16 changes: 8 additions & 8 deletions src/CoreEx.Validation/ValidationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,7 +1280,7 @@ public static IPropertyRule<TEntity, TProperty> IsValid<TEntity, TProperty>(this
/// <param name="maxCount">The maximum count.</param>
/// <param name="errorText">The error message format text <see cref="LText"/> (overrides the default).</param>
/// <returns>A <see cref="IPropertyRule{TEntity, TProperty}"/>.</returns>
public static IPropertyRule<TEntity, TProperty?> AreValid<TEntity, TProperty>(this IPropertyRule<TEntity, TProperty?> rule, bool allowDuplicates = false, int minCount = 0, int? maxCount = null, LText? errorText = null) where TEntity : class where TProperty : IReferenceDataCodeList
public static IPropertyRule<TEntity, TProperty> AreValid<TEntity, TProperty>(this IPropertyRule<TEntity, TProperty> rule, bool allowDuplicates = false, int minCount = 0, int? maxCount = null, LText? errorText = null) where TEntity : class where TProperty : IReferenceDataCodeList?
=> rule.ThrowIfNull(nameof(rule)).AddRule(new ReferenceDataSidListRule<TEntity, TProperty> { AllowDuplicates = allowDuplicates, MinCount = minCount, MaxCount = maxCount, ErrorText = errorText });

/// <summary>
Expand Down Expand Up @@ -1577,7 +1577,7 @@ public static IPropertyRule<TEntity, TProperty> Default<TEntity, TProperty>(this
/// <param name="name">The value name (defaults to <see cref="Validation.ValueNameDefault"/>).</param>
/// <param name="text">The friendly text name used in validation messages (defaults to <paramref name="name"/> as sentence case where not specified).</param>
/// <returns>A <see cref="ValueValidator{T}"/>.</returns>
public static ValueValidator<T> Validate<T>(this T value, string? name = null, LText? text = null) => new(value, name, text);
public static ValueValidator<T> Validate<T>(this T? value, string? name = null, LText? text = null) => new(value, name, text);

/// <summary>
/// Enables (sets up) validation for a value.
Expand All @@ -1588,7 +1588,7 @@ public static IPropertyRule<TEntity, TProperty> Default<TEntity, TProperty>(this
/// <param name="name">The value name (defaults to <see cref="Validation.ValueNameDefault"/>).</param>
/// <param name="text">The friendly text name used in validation messages (defaults to <paramref name="name"/> as sentence case where not specified).</param>
/// <returns>A <see cref="ValueValidator{T}"/>.</returns>
public static ValueValidator<T> Validate<T>(this T value, Action<ValueValidatorConfiguration<T>> configure, string? name = null, LText? text = null)
public static ValueValidator<T> Validate<T>(this T? value, Action<ValueValidatorConfiguration<T>> configure, string? name = null, LText? text = null)
=> new ValueValidator<T>(value, name, text).Configure(configure);

/// <summary>
Expand All @@ -1600,7 +1600,7 @@ public static ValueValidator<T> Validate<T>(this T value, Action<ValueValidatorC
/// <param name="name">The value name (defaults to <see cref="Validation.ValueNameDefault"/>).</param>
/// <param name="text">The friendly text name used in validation messages (defaults to <paramref name="name"/> as sentence case where not specified).</param>
/// <returns>A <see cref="ValueValidator{T}"/>.</returns>
public static ValueValidator<T> Validate<T>(this T value, CommonValidator<T> validator, string? name = null, LText? text = null)
public static ValueValidator<T> Validate<T>(this T? value, CommonValidator<T> validator, string? name = null, LText? text = null)
=> new ValueValidator<T>(value, name, text).Configure(c => c.Common(validator));
#else
/// <summary>
Expand All @@ -1611,7 +1611,7 @@ public static ValueValidator<T> Validate<T>(this T value, CommonValidator<T> val
/// <param name="name">The value name (defaults to <paramref name="value"/> name using the <see cref="CallerArgumentExpressionAttribute"/>).</param>
/// <param name="text">The friendly text name used in validation messages (defaults to <paramref name="name"/> as sentence case where not specified).</param>
/// <returns>A <see cref="ValueValidator{T}"/>.</returns>
public static ValueValidator<T> Validate<T>(this T value, [CallerArgumentExpression(nameof(value))] string? name = null, LText? text = null) => new(value, name, text);
public static ValueValidator<T> Validate<T>(this T? value, [CallerArgumentExpression(nameof(value))] string? name = null, LText? text = null) => new(value, name, text);

/// <summary>
/// Enables (sets up) validation for a value.
Expand All @@ -1622,7 +1622,7 @@ public static ValueValidator<T> Validate<T>(this T value, CommonValidator<T> val
/// <param name="name">The value name (defaults to <paramref name="value"/> name using the <see cref="CallerArgumentExpressionAttribute"/>).</param>
/// <param name="text">The friendly text name used in validation messages (defaults to <paramref name="name"/> as sentence case where not specified).</param>
/// <returns>A <see cref="ValueValidator{T}"/>.</returns>
public static ValueValidator<T> Validate<T>(this T value, Action<ValueValidatorConfiguration<T>> configure, [CallerArgumentExpression(nameof(value))] string? name = null, LText? text = null)
public static ValueValidator<T> Validate<T>(this T? value, Action<ValueValidatorConfiguration<T>> configure, [CallerArgumentExpression(nameof(value))] string? name = null, LText? text = null)
=> new ValueValidator<T>(value, name, text).Configure(configure);

/// <summary>
Expand All @@ -1634,7 +1634,7 @@ public static ValueValidator<T> Validate<T>(this T value, Action<ValueValidatorC
/// <param name="name">The value name (defaults to <paramref name="value"/> name using the <see cref="CallerArgumentExpressionAttribute"/>).</param>
/// <param name="text">The friendly text name used in validation messages (defaults to <paramref name="name"/> as sentence case where not specified).</param>
/// <returns>A <see cref="ValueValidator{T}"/>.</returns>
public static ValueValidator<T> Validate<T>(this T value, CommonValidator<T> validator, [CallerArgumentExpression(nameof(value))] string? name = null, LText? text = null)
public static ValueValidator<T> Validate<T>(this T? value, CommonValidator<T> validator, [CallerArgumentExpression(nameof(value))] string? name = null, LText? text = null)
=> new ValueValidator<T>(value, name, text).Configure(c => c.Common(validator));
#endif

Expand All @@ -1649,7 +1649,7 @@ public static ValueValidator<T> Validate<T>(this T value, CommonValidator<T> val
/// <param name="multiValidator">The <see cref="MultiValidator"/>.</param>
/// <param name="validator">The <see cref="ValueValidator{T}"/>.</param>
/// <returns>The (this) <see cref="MultiValidator"/>.</returns>
public static MultiValidator Add<T>(this MultiValidator multiValidator, ValueValidator<T?> validator)
public static MultiValidator Add<T>(this MultiValidator multiValidator, ValueValidator<T> validator)
{
validator.ThrowIfNull(nameof(validator));
multiValidator.ThrowIfNull(nameof(multiValidator)).Validators.Add(async ct => await validator.ValidateAsync(ct).ConfigureAwait(false));
Expand Down
2 changes: 1 addition & 1 deletion src/CoreEx.Validation/ValueValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class ValueValidator<T>
/// <param name="value">The value to validate.</param>
/// <param name="name">The value name (defaults to <see cref="Validation.ValueNameDefault"/>).</param>
/// <param name="text">The friendly text name used in validation messages (defaults to <paramref name="name"/> as sentence case where not specified).</param>
internal ValueValidator(T value, string? name = null, LText? text = null)
internal ValueValidator(T? value, string? name = null, LText? text = null)
{
_configuration = new ValueValidatorConfiguration<T>(string.IsNullOrEmpty(name) ? Validation.ValueNameDefault : name, text);
_validationValue = new ValidationValue<T>(null, value);
Expand Down
38 changes: 38 additions & 0 deletions tests/CoreEx.Test/Framework/Validation/CommonValidatorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,44 @@ public async Task CreateFor()
});
}

[Test]
public async Task CommonExtensionMethod()
{
await CommonExtensionMethod(null, false);
await CommonExtensionMethod("12345", false);
await CommonExtensionMethod("1234567", true);
}

private async Task CommonExtensionMethod(string? accountId, bool expectErrors)
{
var r = await accountId.Validate().Configure(cv => cv.Common(Validators.String5)).ValidateAsync();
Assert.That(r.HasErrors, Is.EqualTo(expectErrors));
}

[Test]
public async Task CommonEntity()
{
var pv = new PersonValidator();
var r = await pv.ValidateAsync(new Person());
Assert.That(r.HasErrors, Is.False);

r = await pv.ValidateAsync(new Person { Name = "12345" });
Assert.That(r.HasErrors, Is.False);

r = await pv.ValidateAsync(new Person { Name = "12345678" });
Assert.That(r.HasErrors, Is.True);
}

public static class Validators
{
public static CommonValidator<string> String5 => CommonValidator.Create<string>(c => c.String(5));
}

public class PersonValidator : Validator<Person>
{
public PersonValidator() => HasProperty(x => x.Name, p => p.Common(Validators.String5));
}

public class Person
{
public string? Name { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,46 @@ public async Task SidList_Validate()
Assert.That(v1.Messages[0].Property, Is.EqualTo("value"));
});
}

[Test]
public async Task Entity_Sids()
{
IServiceCollection sc = new ServiceCollection();
sc.AddLogging();
sc.AddJsonSerializer();
sc.AddExecutionContext();
sc.AddScoped<RefDataProvider>();
sc.AddReferenceDataOrchestrator<RefDataProvider>();
var sp = sc.BuildServiceProvider();

ReferenceDataOrchestrator.SetCurrent(sp.GetRequiredService<ReferenceDataOrchestrator>());

using var scope = sp.CreateScope();
var ec = scope.ServiceProvider.GetService<ExecutionContext>();

var rde = new RDEntity() { Refs = ["X"] };
var v1 = await rde.Validate().Configure(c => c.Entity(new RDValidator())).ValidateAsync();
Assert.Multiple(() =>
{
Assert.That(v1.HasErrors, Is.True);
Assert.That(v1.Messages!, Has.Count.EqualTo(1));
Assert.That(v1.Messages![0].Text, Is.EqualTo("Refs contains one or more invalid items."));
Assert.That(v1.Messages[0].Type, Is.EqualTo(MessageType.Error));
Assert.That(v1.Messages[0].Property, Is.EqualTo("rde.Refs"));
});
}

public class RDEntity
{
public ReferenceDataCodeList<RefDataEx>? Refs { get; set; }
}

public class RDValidator : Validator<RDEntity>
{
public RDValidator()
{
HasProperty(x => x.Refs, p => p.AreValid());
}
}
}
}

0 comments on commit e5b0ee0

Please sign in to comment.