bartoszlenar / Validot

Validot is a performance-first, compact library for advanced model validation. Using a simple declarative fluent interface, it efficiently handles classes, structs, nested members, collections, nullables, plus any relation or combination of them. It also supports translations, custom logic extensions with tests, and DI containers.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

AsType scope command - validate as different type

bartoszlenar opened this issue · comments

Feature description

Feature in action

Full custom option:

Specification<CustomType> customTypeSpecification = s => s;

TryConvertDelegate<int, CustomType> intToCustomType = (int input, out CustomType output) =>
{
    if (input < 0)
    {
        output = null;
        return false;
    }

    output = new CustomType(input);

    return true;
};

Specification<int> specification = s => s
    .AsType<CustomType>(customTypeSpecification)
    .WithConversion(intToCustomType) // might be required for custom conversion
    .WithConversionErrorMessage("Conversion error!") // optional, if not present, message would be taken from dict;

Predefined options:

Specification<int> specification = s => s
    .AsString(stringSpecification);

Specification<string> specification = s => s
    .AsInt(intSpecification)
    .WithConversionErrorMessage("Invalid string as int!");

Feature details

  • New scope command: AsType<T>.
  • Could (should?) be followed by WithConversion parameter command that would set the conversion logic
    • If not present, throw exception?
    • Enforce WithConversion in fluent api? It is possible if AsType would allow only one following command and NOT ISpecificationOut.
  • WithConversionErrorMessage - optional, setting error message.
  • Plenty of built-in converters. AsInt, AsString, etc.

Hello @bartoszlenar, I'd like to know if there's any pans of adding this feature?
Thank you a lot for your work on this library!

Hi @tim-fay. Sorry for the late reply, I'm on my holidays until the end of month.

I haven't abandoned the project, but the pace slowed down significantly lately. Partially because I don't know what other developers really want from this lib. And now I do, thanks to you.

Thank you for adding your comment and please expect this feature... well... this year for sure. Alongside other features I'm slowly (but consistently!) adding to the codebase.

@tim-fay I'm on the task and so far, this is the progress with the planning:

  • The fluent API command syntax will be .AsType(tryConvertFunction, specification), so everything in a single one, without a separate command for the error message. Why? AsType<TargetType> doesn't work in the fluent API unfortunately, because all commands already have the first generic parameter. So it's either taken from the arguments, or you need to deliver both generic parameter (like AsType<TSource, TTarget>). Same reason for specification as the second parameter - it's just convenient to deliver the conversion method first so then compiler knows what is the TTarget in the Specification<TTarget>.
  • The context value either passes the conversion and the validation is continued with the delivered specification (in the same path) or doesn't pass the conversion and nothing happens (no error whatsoever). If the error is needed for some reason, that would be a subject for a custom rule.
  • Additionally, .AsType(convertFunction, specification) will be delivered which works exactly the same, but it doesn't assume the conversion could fail.

Please expect the feature sooner rather than later 😄

The final version for this api is:

.AsConverted(converted, specification).

  • converter is the standard dotnet's Converter<TInput, TOutput>
  • specification is of type Specifiction<TOutput>, where TOutput is determined by the given converted declaration
  • AsType becomes AsConverted, because technically nothing stops you from using it as a method to pre-process the value before the further validation (so no change of type, just a little bit of work over the scope value)
  • For now, AsConverted doesn't assume the conversion could fail. You can always add WithCondition to make it conditional. If a try-DoSomething mechanism is required, it will be added in the subsequent versions.

Merged to the main branch with this commit: d379a99

Merged to the main branch with this commit: d379a99

Thanks so much, @bartoszlenar ! Really appreciate you for this PR and the whole project!