Skip to content

Repository files navigation

AutoValidate.Generator

NuGetNuGet DownloadsCILicense: MIT.NET 10 Ready

Compile-time FluentValidation wiring for .NET.

AutoValidate.Generator uses Roslyn source generators to automatically discover your AbstractValidator<T> subclasses and generate AddValidators() on IServiceCollection — no assembly scanning, no reflection, no runtime overhead.


Installation

dotnet add package AutoValidate.Generator
dotnet add package FluentValidation

Quick Start

Define your validators as normal:

publicclassOrder{publicstringCustomerName{get;set;}="";publicdecimalTotal{get;set;}}publicclassOrderValidator:AbstractValidator<Order>{publicOrderValidator(){RuleFor(x =>x.CustomerName).NotEmpty();RuleFor(x =>x.Total).GreaterThan(0);}}

Register everything in one line — no manual wiring:

builder.Services.AddValidators();

AutoValidate discovers every non-abstract AbstractValidator<T> in your assembly at compile time and generates the registration code for you.


Attributes

[SkipValidator]

Exclude a validator from auto-registration (e.g. test validators, base classes you register manually):

[SkipValidator]publicclassTestOrderValidator:AbstractValidator<Order>{}

[ValidatorLifetime]

Override the DI lifetime. Default is Scoped.

usingAutoValidate;// Singleton — validator has no mutable state[ValidatorLifetime(ValidatorLifetime.Singleton)]publicclassConfigValidator:AbstractValidator<AppConfig>{}// Transient — validator has per-request dependencies[ValidatorLifetime(ValidatorLifetime.Transient)]publicclassRequestValidator:AbstractValidator<CreateOrderRequest>{}

Available lifetimes: ValidatorLifetime.Scoped (default), ValidatorLifetime.Singleton, ValidatorLifetime.Transient.

[ValidateOnStartup]

Register a hosted service that validates an instance of the model when the application starts. Useful for validating configuration objects.

[ValidateOnStartup]publicclassAppSettingsValidator:AbstractValidator<AppSettings>{publicAppSettingsValidator(){RuleFor(x =>x.ConnectionString).NotEmpty();RuleFor(x =>x.ApiKey).MinimumLength(32);}}

AppSettings must be registered in DI (e.g. via services.AddSingleton(appSettings)). If the instance is not found, startup validation is silently skipped.

If validation fails at startup, an InvalidOperationException is thrown — your app will not start.


Minimal API Integration

WithValidation<T>() attaches a validation endpoint filter that automatically returns 400 ValidationProblem for invalid requests:

app.MapPost("/orders",(Orderorder)=>Results.Ok()).WithValidation<Order>();

The generated ValidationFilter<T> resolves IValidator<T> from DI, validates the first matching argument, and returns RFC 7807-compliant validation errors.

Requires .NET 7 or later.


How It Works

At build time, the generator:

  1. Scans all type declarations with a base list
  2. Walks the inheritance chain looking for FluentValidation.AbstractValidator<T>
  3. Skips abstract classes and [SkipValidator]-decorated types
  4. Emits AddValidators() with the correct AddScoped / AddSingleton / AddTransient calls
  5. Emits ValidationFilter<T> and ValidatorStartupService<T> helpers as needed

No reflection. No assembly scanning. No runtime cost.


Diagnostics

CodeSeverityDescription
AV001WarningMultiple validators found for the same model type. Only the first is registered.
AV002WarningAutoValidate attribute on a class that does not inherit AbstractValidator<T>.

Comparison with Assembly Scanning

FeatureAddValidatorsFromAssembly()AutoValidate.Generator
DiscoveryRuntime reflectionCompile-time
Registration overheadAssembly scan on startupZero
AOT / NativeAOT compatible
IDE navigation✅ (generated code is inspectable)
Startup validationManual[ValidateOnStartup]

Also by the same author

🌐 Full suite overview: swevo.github.io

PackageDescription
AutoWireCompile-time DI auto-registration — [Scoped]/[Singleton]/[Transient] generates IServiceCollection code. Zero reflection.
AutoMap.GeneratorCompile-time object mapping — [Map(typeof(Dto))] generates ToDto() extension methods. Zero reflection, AOT-safe.
AutoResult.GeneratorCompile-time Result<T> monad — [TryWrap] generates Try*() wrappers for sync, async and void methods.
AutoQuery.GeneratorCompile-time LINQ query specs — [QuerySpec(typeof(T))] generates Apply(IQueryable<T>).
AutoDispatch.GeneratorCompile-time CQRS dispatcher — [Handler] generates a strongly-typed IDispatcher. No IRequest<T>, no reflection.
AutoLog.GeneratorCompile-time high-performance logging — [Log(Level, Message)] on a partial method generates LoggerMessage.Define. AOT-safe.
AutoHttpClient.GeneratorCompile-time typed HTTP client — [HttpClient] on an interface generates a strongly-typed client. AOT-safe Refit alternative.

Related Packages

PackageDownloadsDescription
AutoWireDownloadsCompile-time dependency injection auto-registration for
AutoMap.GeneratorDownloadsCompile-time object mapping for
AutoQuery.GeneratorDownloadsCompile-time query composition for IQueryable using Roslyn incremental source generators
AutoArchitectureDownloadsCompile-time architecture/dependency-rule enforcement for
AutoHttpClient.GeneratorDownloadsCompile-time typed HTTP client generation for
AutoDispatch.GeneratorDownloadsCompile-time CQRS dispatcher for
AutoLog.GeneratorDownloadsCompile-time high-performance logging for

License

MIT © Justin Bannister

About

Compile-time FluentValidation wiring for .NET using Roslyn source generators

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages