I've recently discovered the System.ComponentModel.DataAnnotations namespace. This is a collection of Attributes you can use to markup your data objects with conditions, like the following.
public class Person
{
[StringLength(20), Required(ErrorMessage = "Name is a required property")]
public string Name { get; set; }
[Range(0, 150)]
public int Age { get; set; }
[RegularExpression(@"(?i:^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$)")]
public string Email { get; set; }
}
Let's say that you use this Person object to store user input, you can easily validate that input meets the requirements of the annotations.
var person = new Person
{
Name = "John Doe",
Age = 54,
Email = "john.doe@aol.com"
};
/* Validate */
var result = person.ValidateAnnotations();
What I find even more interesting is that you can annotate a contract and just let your model object inherit the annotations. Consider the following.
[MetadataType(typeof(IPerson))]
public class Person : IPerson
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
public interface IPerson
{
[StringLength(20), Required(ErrorMessage = "Name is a required property")]
string Name { get; set; }
[Range(0, 150)]
int Age { get; set; }
[RegularExpression(@"(?i:^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$)")]
string Email { get; set; }
}
Now that's hot! The annotations are actually part of the interface IPerson that specifies what an IPerson is. Then the concrete Person class just implements that contract. Neat! My validating extension method and some tests can be downloaded from here. Enjoy!

5 Comments
Mikael Lundin said
Yes it should if your custom attribute inherits from the ValidationAttribute in System.ComponentModel.DataAnnotations namespace.
D High said
I have a question does your validation runner handle custom attributes or does it?
Alexander said
This seems nice, but what I would like is something like this but part of the type system. If you have a subtype of string that should only be able to contain email, why cant it Castro an exception egen you try to cram somethibg Else in there. You would get the similar casting constraints as normal subtypes.
Mikael Lundin said
You can accomplish that by overloading your data objects and validate data as it is being set. That could be useful in a view model for validating user input. Not so sure about data models where null values may get loaded from a database column, and you need to handle that.
I'm not a big fan of implicit validation. It is a nice thought to always have a valid model, but for testing it can be a total pain.
Alex said
Hmm, my iphone did some strange things to my last comment :)
I agree that over strict systems tend to do more harm than good. And exceptions has never really been that nice. Imagine being forced to have a try/catch around each string assignment :) I think this idea needs to stay at the 'that would be interessting' level. And as you say, you could do the validation in the getters/setters.