0

I have the following piece of code which doesn't seem to be acting right. There is a property which has one attribute which is not of type FieldMapAttribute, but still it goes into the if condition where I am checking the count matching that type of attribute.

foreach (PropertyInfo _property in _properties)
{
    var attributes = _property.GetCustomAttributes(false);
    if (attributes.Select(a => a.GetType() == typeof(FieldMapAttribute)).Count() > 0)
    {
        colname = (attributes.Select(a => a.GetType() == typeof(FieldMapAttribute)).Cast<FieldMapAttribute>().First()).DbColumnName;
    }
}

Can someone help me to understand what is going on here?

2 Answers 2

5

Assuming what you're trying to do is check whether a FieldMapAttribute attribute exists on the property, you should use

var attributes = _property.GetCustomAttributes(typeof(FieldMapAttribute), false);
if (attributes.Length > 0)
{
    ...
}

Another option is to use

if (attributes.OfType<FieldMapAttribute>().Any())

You should note that the way you use Select is incorrect. Select is used to project elements into a new form. Your Select statement returns a list of bools - one for each attribute the property has (any attribute, not just of type FieldMapAttribute). This means that if your property looked like this

[SomeAttribute]
[SomeOtherAttribute]
[FieldMapAttribute]
public string MyProp { get; set; }

Then your select statement would yield the following result

false
false
true

As you can see, calling Count on this result set will always return the number of custom attributes set on the property (again, any attribute).

Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

Not my downvote, but PropertyInfo.IsDefined is a simpler approach for the test.
Both the answers are very helpful and I really appreciate Jon & Adi both. Thanks guys I seem to be running smoothly again.
2

Regardless of exactly what's going on in your current code, it looks to me like it could be written much more simply:

foreach (PropertyInfo property in properties)
{
    if (property.IsDefined(typeof(FieldMapAttribute), false))
    {
        colName = property.GetCustomAttributes(typeof(FieldMapAttribute), false)
                          .Cast<FieldMapAttribute>()
                          .First()
                          .DbColumnName;            
    }
}

(Note that that will end up with the last property defining the attribute as the one which specifies the column name. Is that what you want?)

Or even using LINQ for the whole thing:

var attrType = typeof(FieldMapAttribute);
var attr = properties.SelectMany(p => p.GetCustomAttributes(attrType), false)
                     .Cast<FieldMapAttribute>()
                     .FirstOrDefault();
if (attr != null)
{
    colName = attr.DbColumnName;
}

4 Comments

I like this approach, but wouldn't this cause looking up the property's attributes twice instead of once in cases where FieldMapAttribute was defined?
@AdiLester: Potentially (although not in the second option). Unless I had any reason to think that was actually a bottleneck though, I wouldn't worry about it.
Thanks Jon...I appreciate your reply and help. :)
Jon I had to make small change in your suggestion to make it work. colname = (_property.GetCustomAttributes(typeof(FieldMapAttribute), false).Cast<FieldMapAttribute>().First()).DbColumnName;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.