Daniel Cazzulino's Blog : Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement

Subscriptions

News

Source code published in this blog is public domain unless otherwise specified.

 

kzu in LinkedIn

  Microsoft MVP Profile

 Contact

Post Categories

Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement

public static IEnumerable<ValidationResult> Validate(object component)
{
    return from descriptor in TypeDescriptor.GetProperties(component).Cast<PropertyDescriptor>()
            from validation in descriptor.Attributes.OfType<System.ComponentModel.DataAnnotations.ValidationAttribute>()
            where !validation.IsValid(descriptor.GetValue(component))
            select new ValidationResult(
                validation.ErrorMessage ?? string.Format(CultureInfo.CurrentUICulture, "{0} validation failed.", validation.GetType().Name),
                new[] { descriptor.Name });
}

Enjoy!

posted on Thursday, April 15, 2010 10:08 AM by kzu

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Thursday, April 15, 2010 10:16 AM

Very cool!

To support localization, you should be calling validation.FormatErrorMessage() rather than validation.ErrorMessage.

Brad Wilson

# Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Thursday, April 15, 2010 10:28 AM

public static IEnumerable&amp;amp;lt;ValidationResult&amp;amp;gt; Validate(object component) { return from descriptor

Anonymous

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Saturday, April 17, 2010 10:57 AM

Good solution!

One addition to this. If you are using a 'buddy' class for the metadata (ie your validation attributes are in another class associated with [MetadataType(typeof(...))]) you need to register these associations by hand for unit testing (no framework to do it for you) using something like:

TypeDescriptor.AddProvider(new AssociatedMetadataTypeTypeDescriptionProvider(model.GetType()), model.GetType());

Jaime del Palacio

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Monday, April 19, 2010 1:22 AM

What is this? A Perl contest in the 90s? Try this: http://www.refactoring.com/catalog/extractMethod.html

Dennis

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Monday, April 19, 2010 5:49 AM

This is a brilliant example of the kind of code we should strive to avoid.
It's unreadable and difficult to maintain, and every time someone looks at it they will need to stare at it for about 5-10 minutes to work out what the hell it is doing...

Pray tell: what exactly is the advantage of doing this in a single statement?

anon

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Thursday, April 22, 2010 12:31 AM

When I do my coding in Visual studio, I use this nifty little tool called ReSharper. It sometimes suggests that I refactor a fairly large block of code into a huge lambda statement instead. I do it, look at it for a while and after that, fervently press ctrl+z. While Linq is Cool and Immensely Useful - it can also be unreadable and hard to maintain. Would you really keep a statement like that in production code? And if so, why? A keen desire to have code as terse as possible?

Ciddan

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Thursday, April 22, 2010 7:50 PM

This is a brilliant example of the kind of code we need more of.
Every time someone looks at it they will need to stare at it for about 5-10 minutes to work out what the hell it is doing...it's called thinking.

anon

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Friday, April 23, 2010 4:19 AM

Have you thought about INTERCAL?

CADIE

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Friday, May 14, 2010 4:29 AM

I agree it takes some time to getting used to it.
We're TOO used to reading imperative code. You expect foreach, if..else, etc.

If you have trouble reading this query and simple projection, then I can almost guarantee you haven't been looking at SQL queries for a while too, because it's almost exactly the same.

Thinking in queries makes it easier, not harder to reason about the code.I should probably start posting the Linq way and the imperative way for people to compare.

No question, many will find the multiple nested foreach and if..else more familiar, but it hardly conveys the meaning of code any better...

kzu

# re: Crazy Linq: performing System.ComponentModel.DataAnnotations validation in a single statement @ Sunday, May 30, 2010 9:33 AM

Hi Daniel,

again another great post!
Keep up with interesting topics !

Here is the code for silverlight RIA Services Entity validation:

return
(from propertyInfo in component.GetType().GetProperties().Cast<System.Reflection.PropertyInfo>()
from validation in propertyInfo.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.ValidationAttribute), true)
where validation is System.ComponentModel.DataAnnotations.ValidationAttribute
select ((System.ComponentModel.DataAnnotations.ValidationAttribute)validation).GetValidationResult(propertyInfo.GetValue(component, null), context))
.Union(
from validation in component.GetType().GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.ValidationAttribute), true)
where validation is System.ComponentModel.DataAnnotations.ValidationAttribute
select ((System.ComponentModel.DataAnnotations.ValidationAttribute)validation).GetValidationResult(component, context)
).Where(c => c != null && c != ValidationResult.Success).ToList();

Thanks,
Kirill

Kirill Chilingarashvili