views:

61

answers:

2

I´m working on some validation code and having some issues with my Linq code.

What I have is a class that validates on a particular attribute (ValidationAttribute). That all works fine, ie the validation works with a class that has some properties decorated with that attribute (or subclasses of it).

What I now want to accomplish is to tell my "validator" class to ignore all properties that are marked with a certain other attribute (let´s call that IgnoreAttribute).

So my question is, how do I first find all the properties with the validation attribute (which I have code for already) but first "filter" that collection to ignore the properties that have the ignore attribute (or actually a List collection).

The code for the validation looks like:

from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>()
                   from attribute in prop.Attributes.OfType<ValidationAttribute>().
                   where attribute.IsValid(prop.GetValue(instance)) == false
                   select new ...etc

I want this code to ignore all attributes contained in a List that I have in the class, ie some sort of filtering on the original set...

Any ideas?

UPDATE:

I guess my question is really this: If I have a class that has its properties decorated with attributes like:

class MyClass

[Required]
public string MyProp { get; set; }

[Required]
[Ignore]
public string MyProp2 { get; set; }

How do I find all the properties that have the validation attribute (required inherits that)) but not the ignore attribute? Although I really wan´t it to ignore a list of attributes and not only the ignore attribute.

+1  A: 

Do you need the PropertyDescriptor flexible model? Pretty easy with reflection:

    var filtered = instance.GetType().GetProperties()
        .Where(prop => !Attribute.IsDefined(prop, typeof(IgnoreAttribute)));

Or to do the whole thing:

    var invalid = from prop in instance.GetType().GetProperties()
                   where !Attribute.IsDefined(prop, typeof(IgnoreAttribute))
                   let valAttribs = Attribute.GetCustomAttributes(
                            prop, typeof(ValidationAttribute))
                   where valAttribs != null && valAttribs.Length > 0
                   let value = prop.GetValue(instance, null)
                   from ValidationAttribute valAttrib in valAttribs
                   where !valAttrib.IsValid(value)
                   select new {};
Marc Gravell
What I really want is to have one collection (of all the validation attributes) but if that property is also decorated with one of the attributes in another list of attributes it is supposed to ignore that...any clearer??It really has nothing to do with attributes just Linq filtering
Johan Leino
@Johan - exactly; the IsDefined takes those properties away earlier. Is the update any clearer?
Marc Gravell
+1  A: 

Not Any?

from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>() 
where !prop.Attributes.OfType<IgnoreAttribute>().Any()
from attribute in prop.Attributes.OfType<ValidationAttribute>(). 
where attribute.IsValid(prop.GetValue(instance)) == false 
select new ...etc 
David B
@David B: Yep, that worked...why didn´t I think of that..bummer? Thanks and sorry for the late answer!
Johan Leino