Repository navigation
Releases
10.1.1
10.1.0
Validate nested options reliably and name the options type in failures
The recursive validation looked each property up again by name, so a
property hidden with new and another type threw AmbiguousMatchException.
It also stopped startup on valid options: it read static properties, where
a default instance recursed until the stack overflowed, and descended into
framework objects whose getters throw or never end (a Type, a delegate, a
relative Uri, some certificates, a FileInfo). It compared visited objects by
value, so an equal but distinct object was not validated.
The validator walks the most derived readable declaration of each public
instance property and reads it through its PropertyInfo. Visited objects
are compared by reference, and a depth of 32 bounds computed properties
that return a new object on each read. Strings, primitives and enums are
skipped, and dictionary entries are still validated. Delegates, reflection
types, Uri, X509Certificate and FileSystemInfo are not descended.
Each validation result becomes one failure, worded as the .NET
ValidateDataAnnotations words it and naming the options type. The README
describes the failure message, what the recursion covers and how it
compares with the .NET validation.
BREAKING CHANGE: OptionsValidationException.Failures holds one entry per
validation error, naming the options type, instead of a single string that
joined every error. A base property hidden with new and static properties
are no longer validated. TryValidateObjectRecursive throws
ArgumentNullException for a null object.