Skip to content

Commit

Permalink
Add more ways to extract the error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
mr5z committed Apr 10, 2021
1 parent d84afa6 commit 4363528
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 24 deletions.
13 changes: 13 additions & 0 deletions PropertyValidator/Exceptions/PropertyException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using PropertyValidator.Models;
using System;

namespace PropertyValidator.Exceptions
{
public class PropertyException : Exception
{
public PropertyException(ValidationResultArgs validationResultArgs) : base(validationResultArgs.FirstError)
{

}
}
}
2 changes: 1 addition & 1 deletion PropertyValidator/Models/MultiValidationRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ private void Target_PropertyChanged(object sender, PropertyChangedEventArgs e)
// TODO convert to List<string>
public override sealed string ErrorMessage => $"[{string.Join(",", ErrorsAsJsonString())}]";

private IEnumerable<string> ErrorsAsJsonString()
private IEnumerable<string?> ErrorsAsJsonString()
=> validationRules
.Where(e => e.HasError)
.Select(e => $"{e.PropertyName}:\"{e.ErrorMessage}\"");
Expand Down
6 changes: 3 additions & 3 deletions PropertyValidator/PropertyValidator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
<PackageProjectUrl>https://github.com/mr5z/PropertyValidator</PackageProjectUrl>
<RepositoryUrl>https://github.com/mr5z/PropertyValidator</RepositoryUrl>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<FileVersion>1.0.6.1</FileVersion>
<AssemblyVersion>1.0.6.1</AssemblyVersion>
<Version>1.0.6.1</Version>
<FileVersion>1.0.6.2</FileVersion>
<AssemblyVersion>1.0.6.2</AssemblyVersion>
<Version>1.0.6.2</Version>
<NeutralLanguage>en</NeutralLanguage>
</PropertyGroup>

Expand Down
44 changes: 38 additions & 6 deletions PropertyValidator/Services/IValidationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,55 @@ namespace PropertyValidator.Services
{
public interface IValidationService
{
// For registration
/// <summary>
/// Registers the model for validation
/// </summary>
/// <typeparam name="TNotifiableModel"></typeparam>
/// <param name="notifiableModel">The notifiable model</param>
/// <param name="autofill">If true, it will automatically fills the error properties</param>
/// <param name="delay">Delays the fill up of error properties</param>
/// <returns>RuleCollection so that it can be chained</returns>
RuleCollection<TNotifiableModel> For<TNotifiableModel>(
TNotifiableModel notifiableModel,
bool autofill = false,
TimeSpan? delay = null)
where TNotifiableModel : INotifyPropertyChanged;

// Retrieve error messages per property
/// <summary>
/// Retrieve error messages per property
/// </summary>
/// <typeparam name="TNotifiableModel"></typeparam>
/// <param name="_">Unused</param>
/// <param name="expression">Expression to extract the property name from the target class</param>
/// <returns>The first error message</returns>
string? GetErrorMessage<TNotifiableModel>(
TNotifiableModel notifiableModel,
Expression<Func<TNotifiableModel, object>> expression)
TNotifiableModel _,
Expression<Func<TNotifiableModel, object?>> expression)
where TNotifiableModel : INotifyPropertyChanged;

// Manually trigger the validation
/// <summary>
/// Retrieve error messages per property
/// </summary>
/// <typeparam name="TNotifiableModel"></typeparam>
/// <param name="propertyName">The name of the property the exist within the registered notifiable model</param>
/// <returns>The first error message</returns>
string? GetErrorMessage<TNotifiableModel>(string propertyName);

/// <summary>
/// Ensure all properties are in a valid state based from the provided validation rules
/// </summary>
/// <throws>PropertyException if there is an error</throws>
void EnsurePropertiesAreValid();

/// <summary>
/// Trigger manually the validation
/// </summary>
/// <returns></returns>
bool Validate();

// Subscribe to error events (cleared/raised)
/// <summary>
/// Subscribe to error events (cleared/raised)
/// </summary>
event EventHandler<ValidationResultArgs>? PropertyInvalid;
}
}
43 changes: 29 additions & 14 deletions PropertyValidator/Services/ValidationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics.CodeAnalysis;
using PropertyValidator.Exceptions;

namespace PropertyValidator.Services
{
Expand Down Expand Up @@ -97,13 +98,7 @@ private async Task PropertyChangedAsync(object sender, PropertyChangedEventArgs

Validate(e.PropertyName);

var errorMessages = GetRules()
.Where(it => it.HasError && it.PropertyName == e.PropertyName)
.Select(it => new { it.PropertyName, ErrorMessage = it.Error })
.GroupBy(it => it.PropertyName)
.ToDictionary(group => group.Key, g => g.Select(it => it.ErrorMessage));

var eventArgs = new ValidationResultArgs(e.PropertyName, errorMessages);
var eventArgs = GetValidationResultArgs(e.PropertyName);
if (autofill)
{
EnsureEntryMethodInvoked();
Expand All @@ -112,12 +107,8 @@ private async Task PropertyChangedAsync(object sender, PropertyChangedEventArgs
PropertyInvalid?.Invoke(this, eventArgs);
}

public List<string?> GetErrorMessages<TNotifiableModel>(
TNotifiableModel _,
Expression<Func<TNotifiableModel, object>> expression)
where TNotifiableModel : INotifyPropertyChanged
private List<string?> GetErrorMessages(string propertyName)
{
var propertyName = expression.GetMemberName();
return GetRules()
.Where(it => it.HasError && it.PropertyName == propertyName)
.Select(it => it.Error)
Expand All @@ -126,10 +117,16 @@ private async Task PropertyChangedAsync(object sender, PropertyChangedEventArgs

public string? GetErrorMessage<TNotifiableModel>(
TNotifiableModel notifiableProperty,
Expression<Func<TNotifiableModel, object>> expression)
Expression<Func<TNotifiableModel, object?>> expression)
where TNotifiableModel : INotifyPropertyChanged
{
return GetErrorMessages(notifiableProperty, expression).FirstOrDefault();
var propertyName = expression.GetMemberName();
return GetErrorMessages(propertyName).FirstOrDefault();
}

public string? GetErrorMessage<TNotifiableModel>(string propertyName)
{
return GetErrorMessages(propertyName).FirstOrDefault();
}

public bool HasError()
Expand All @@ -147,6 +144,16 @@ public bool Validate([NotNull] string propertyName)
return ValidateImpl(propertyName);
}

private ValidationResultArgs GetValidationResultArgs(string propertyName)
{
var errorMessages = GetRules()
.Where(it => it.HasError && it.PropertyName == propertyName)
.Select(it => new { it.PropertyName, ErrorMessage = it.Error })
.GroupBy(it => it.PropertyName)
.ToDictionary(group => group.Key, g => g.Select(it => it.ErrorMessage));
return new ValidationResultArgs(propertyName, errorMessages);
}

private bool ValidateImpl(string? propertyName = null)
{
EnsureEntryMethodInvoked();
Expand Down Expand Up @@ -177,5 +184,13 @@ public static bool ValidateRuleCollection(
}
return noErrors;
}

public void EnsurePropertiesAreValid()
{
var resultArgs = GetValidationResultArgs(string.Empty);
var firstError = resultArgs.FirstError;
if (!string.IsNullOrEmpty(firstError))
throw new PropertyException(resultArgs);
}
}
}

0 comments on commit 4363528

Please sign in to comment.