3. Creating and Using Individual Validators
You can create an instance of any of the validators included in
the Validation block directly in your code, and then call its Validate method to validate an object or value.
For example, you can create a new Date Time Range validator and set
the properties, such as the upper and lower bounds, the message, and
the TagValidate method of the validator,
specifying the object or value you want to validate. The
example, Creating and Using Validators Directly,
demonstrates the creation and use of some of the individual and
composite validators provided with the Validation block. property. Then you call the
Validating Strings for Contained Characters
The example code first creates a ContainsCharactersValidator
that specifies that the validated value must contain
the characters c, a, and t, and that it must contain all of these
characters (you can, if you wish, specify that it must only contain
Any of the characters). The code also
sets the Tag property to a
user-defined string that helps to identify the validator in the list
of errors. The overload of the Validate method used here returns a new
ValidationResults instance containing
a ValidationResult instance for each
validation error that occurred.
// Create a Contains Characters Validator and use it to validate a string.
Validator charsValidator = new ContainsCharactersValidator("cat",
ContainsCharacters.All,
" Value must contain {4} of the characters '{3}'.");
charsValidator.Tag = "Validating the String value 'disconnected'";
ValidationResults valResults = charsValidator.Validate("disconnected");
Validating Integers within a Domain
Next, the example code creates a new DomainValidator for integer values,
specifying an error message and an array of acceptable values. Then
it can be used to validate an integer, with a reference to the
existing ValidationResults instance
passed to the Validate method this
time.
// Create a Domain Validator and use it to validate an Integer value.
Validator integerValidator = new DomainValidator<int>(
"Value must be in the list 1, 3, 7, 11, 13.",
new int[] {1, 3, 7, 11, 13});
integerValidator.Tag = "Validating the Integer value '42'";
integerValidator.Validate(42, valResults);
Validating with a Composite Validator
To show how you can create composite validators, the next section of the example
creates an array containing two validators: a NotNullValidator and a StringLengthValidator. The first parameter of
the NotNullValidator sets the Negated property. In this example, we set it
to true so that the validator will allow null values. The StringLengthValidator specifies that the
string it validates must be exactly five characters long. Notice
that range validators such as the StringLengthValidator have properties that
specify not only the upper and lower bound values, but also whether
these values are included in the valid result set (RangeBoundaryType.Inclusive) or excluded
(RangeBoundaryType.Exclusive). If you
do not want to specify a value for the upper or lower bound of a range validator, you
must set the corresponding property to RangeBoundaryType.Ignore.
Validator[] valArray = new Validator[]
{
new NotNullValidator(true, "Value can be NULL."),
new StringLengthValidator(5, RangeBoundaryType.Inclusive,
5, RangeBoundaryType.Inclusive,
"Must be between {3} ({4}) and {5} ({6}) chars.")
};
Having created an array of validators, we can now use this to
create a composite validator. There are two composite validators,
the AndCompositeValidator
and the OrCompositeValidator
. You can combine these as well to create any nested
hierarchy of validators you require, with each combination returning
a valid result if all (with the AndCompositeValidator) or any (with the
OrCompositeValidator) of the
validators it contains are valid. The example creates an OrCompositeValidator, which will return true
(valid) if the validated string is either null or contains exactly
five characters. Then it validates a null value and an invalid
string, passing into the Validate
method the existing ValidationResults
instance.
Validator orValidator = new OrCompositeValidator(
"Value can be NULL or a string of 5 characters.",
valArray);
// Validate two values with the Or Composite Validator.
orValidator.Validate(null, valResults);
orValidator.Validate("MoreThan5Chars", valResults);
Validating Single Members of an Object
The Validation block contains three validators you can use
to validate individual members of a class directly, instead of
validating the entire type using attributes or rule sets. Although
you may not use this approach very often, you might find it to be
useful in some scenarios. The Field Value validator can be used to
validate the value of a field of a type. The Method Return Value
validator can be used to validate the return value of a method of a
type. Finally, the Property Value validator can be used to validate the
value of a property of a type.
The example shows how you can use a Property Value validator.
The code creates an instance of the Product class that has an invalid value for
the ID property, and then creates an instance of the PropertyValueValidator class, specifying the
type to validate and the name of the target property. This second
parameter of the constructor is the validator to use to validate the
property value—in this example a Regular Expression validator. Then
the code can initiate validation by calling the Validate method, passing in the existing
ValidationResults instance, as shown
here.
IProduct productWithID = new Product();
PopulateInvalidProduct(productWithID);
Validator propValidator = new PropertyValueValidator<Product>("ID",
new RegexValidator("[A-Z]{2}[0-9]{4}",
"Product ID must be 2 capital letters and 4 numbers.")
);
propValidator.Validate(productWithID, valResults);
If required, you can create a composite validator containing a
combination of validators, and specify this composite validator in
the second parameter. A similar technique can be used with the Field
Value validator and Method Return Value validator.
After performing all of the validation operations, the example
displays the results by iterating through the ValidationResults instance that contains the
results for all of the preceding validation operations. This is the result:
The following 4 validation errors were detected:
+ Target object: disconnected, Member:
- Detected by: ContainsCharactersValidator
- Tag value: Validating the String value 'disconnected'
- Message: 'Value must contain All of the characters 'cat'.'
+ Target object: 42, Member:
- Detected by: DomainValidator`1[System.Int32]
- Tag value: Validating the Integer value '42'
- Message: 'Value must be in the list 1, 3, 7, 11, 13.'
+ Target object: MoreThan5Chars, Member:
- Detected by: OrCompositeValidator
- Message: 'Value can be NULL or a string of 5 characters.'
+ Nested validators:
- Detected by: NotNullValidator
- Message: 'Value can be NULL.'
- Detected by: StringLengthValidator
- Message: 'Value must be between 5 (Inclusive) and 5 (Inclusive) chars.'
+ Target object: Product, Member: ID
- Detected by: RegexValidator
- Message: 'Product ID must be 2 capital letters and 4 numbers.'
You can see how the message template tokens create the content
of the messages that are displayed, and the results of the nested
validators we defined for the Or Composite validator. If you want to
experiment with individual validators, you can modify and extend this
example routine to use other validators and combinations of
validators.