Skip to main content
Version: 0.3.x (0.3.0)

Class ValueObjectRuleBuilderExtensions

Namespace: AdCodicem.ValueObjects.FluentValidation
Assembly: AdCodicem.ValueObjects.FluentValidation.dll

FluentValidation rules built on the rules a value object already enforces.

public static class ValueObjectRuleBuilderExtensions

Inheritance​

object ← ValueObjectRuleBuilderExtensions

Inherited Members​

object.Equals(object?), object.Equals(object?, object?), object.GetHashCode(), object.GetType(), object.MemberwiseClone(), object.ReferenceEquals(object?, object?), object.ToString()

Remarks​

The point is to state a rule once. A command carrying a raw string for an IBAN should not restate the length, the pattern and the check-digit rule in its validator: it should defer to the value object that owns them, and report the same stable error code the rest of the system uses.

A failure of or carries, by default, the code and the message of the value object's rule that refused the value. The options chained on either replace them as they would on any rule: WithErrorCode, WithMessage, WithSeverity, WithState and WithName. A message template can quote the value object's own message as {Reason}, besides the usual {PropertyName}, {PropertyValue}, {PropertyPath} and, in a child validator run for each element of a collection, {CollectionIndex}. The global options apply as well: the default severity, and the OnFailureCreated callback.

A template can also quote {ValueObject}, the name of the value object type, and the arguments its declared rules supply for the code that refused the value, formatted in the current culture: {MinLength} for value_object.too_short, {MaxLength} for value_object.too_long, {Minimum} and {Maximum} for value_object.out_of_range, either empty when the type declares no such bound, and {KnownValues} for value_object.not_a_known_value, as reads them. FluentValidation leaves a placeholder it has no value for, a positional one included, as it is.

Unless a message is chained, a failure looks its message up in ' LanguageManager, which reads the current UI culture, under the keys of : ValueObject.value_object.too_short, after ValueObject.value_object.out_of_range.minimum or .maximum for a type declaring one bound alone. An application adds its translations to a LanguageManager of its own, as FluentValidation documents it, and the value object's English message, {Reason}, stands for any key it does not translate. The key is that of the code of the value object's rule, whose arguments the message quotes, whatever code WithErrorCode chains. does the same under ValueObject.value_object.required.

Methods​

MustParseAs<T>(IRuleBuilder<T, string?>, Type)​

Requires the text to be acceptable to a value object type.

public static IRuleBuilderOptions<T, string?> MustParseAs<T>(this IRuleBuilder<T, string?> ruleBuilder, Type valueObjectType)

Parameters​

ruleBuilder IRuleBuilder<T, string?>

Rule builder for a text member.

valueObjectType Type

Value object the text must parse into.

Returns​

IRuleBuilderOptions<T, string?>

The rule, so it can be configured further.

Type Parameters​

T

Validated object.

Remarks​

A null passes: whether the member is required is NotNull's or NotEmpty's to say, as everywhere in FluentValidation. Empty text is the value object's to judge, as any text is: a string value object refuses it as required unless it allows empty text, and one over another type cannot parse it.

The value object type is passed as a rather than a type argument so that RuleFor(x => x.Iban).MustParseAs(typeof(Iban)) stays readable: C# cannot infer one type argument while another is given explicitly, and spelling out the validated type at every rule is noise.

MustSatisfy<T, TSelf, TValue>(IRuleBuilder<T, TValue>)​

Requires an underlying value to satisfy the rules of a value object, without constructing it.

public static IRuleBuilderOptions<T, TValue> MustSatisfy<T, TSelf, TValue>(this IRuleBuilder<T, TValue> ruleBuilder) where TSelf : struct, IValueObject<TSelf, TValue>

Parameters​

ruleBuilder IRuleBuilder<T, TValue>

Rule builder for a member holding the underlying value.

Returns​

IRuleBuilderOptions<T, TValue>

The rule, so it can be configured further.

Type Parameters​

T

Validated object.

TSelf

Value object type.

TValue

Underlying value type.

Remarks​

A null passes: whether the member is required is NotNull's or NotEmpty's to say, as everywhere in FluentValidation.

NotDefault<T, TSelf, TValue>(IRuleBuilder<T, TSelf>)​

Requires a value object member not to equal default(TSelf), through .

public static IRuleBuilderOptions<T, TSelf> NotDefault<T, TSelf, TValue>(this IRuleBuilder<T, TSelf> ruleBuilder) where TSelf : struct, IValueObject<TSelf, TValue>

Parameters​

ruleBuilder IRuleBuilder<T, TSelf>

Rule builder for a value object member.

Returns​

IRuleBuilderOptions<T, TSelf>

The rule, so it can be configured further.

Type Parameters​

T

Validated object.

TSelf

Value object type.

TValue

Underlying value type.

Remarks​

Catches the one hole a struct value object cannot close by itself: an uninitialized instance, which the CLR always allows and which the analyzer only catches where it can see the code.

Over a value type, a constructed instance holding the type's zero (0, , …) equals the default too, so the rule refuses a valid zero as value_object.required. Keep it for a value object over , or over a value type whose rules refuse its zero anyway.

Unless a message is chained, a failure carries the message ' LanguageManager holds under ValueObject.value_object.required for the current UI culture, or '{PropertyName}' is required. when it holds none. A template can quote {ValueObject}, the name of the value object type, besides FluentValidation's own placeholders.