Click here to Skip to main content
Licence CPOL
First Posted 8 Jun 2009
Views 6,914
Bookmarked 7 times

Getting a custom attribute

By Scott Dorman | 8 Jun 2009 | Technical Blog
Attribute programming has a lot of benefits and, when done correctly, can greatly simplify the amount of code that you need to write. One drawback to using attributes is that the code required to retrieve a custom attribute from a type is a bit cumbersome and is very repetitious. Given a type, the

1

2

3
1 vote, 100.0%
4

5
4.00/5 - 1 vote
μ 4.00, σa 5.00 [?]
A Technical Blog article. View original blog here.[]

Attribute programming has a lot of benefits and, when done correctly, can greatly simplify the amount of code that you need to write. One drawback to using attributes is that the code required to retrieve a custom attribute from a type is a bit cumbersome and is very repetitious.

Given a type, the simplest way to retrieve a custom attribute is code like

CustomAttribute attribute = Attribute.GetCustomAttribute(customType.GetType(),
    typeof(CustomAttribute), true) as CustomAttribute;

While this is simple code, it doesn’t handle any error conditions and requires that you always remember to perform the cast. A more complete method would look like

public static CustomAttribute GetAttribute(MemberInfo element)
{
    CustomAttribute attribute = null;

    try
    {
        attribute = Attribute.GetCustomAttribute(element, typeof(CustomAttribute),
            true) as CustomAttribute;
    }
    catch
    {
        // We aren't really interested in the exceptions here, but if we do
        // get an exception just return null;
        attribute = null;
    }

    return attribute;
}

This nicely encapsulates the error handling and casting, but introduces another drawback. In order to make use of this method you would need to include it on every custom attribute you create, being sure to change the types appropriately.

We can make this more practical by changing to a generic extension method with very little effort

public static T GetAttribute<T>(this MemberInfo element) where T: Attribute
{
    T attribute = null;

    if (element != null)
    {
        try
        {
            attribute = Attribute.GetCustomAttribute(element, typeof(T), true) as T;
        }
        catch
        {
            // We aren't really interested in the exceptions here, but if we do
            // get an exception just return null;
            attribute = null;
        }
    }

    return attribute;
}

The benefit here is that, because this is implemented as an extension method it is available as if it were a real method call on any class derived from MemberInfo, which happens to be the base class for all of the Type classes.

Now, we can define our custom attributes without any special consideration to providing a strongly typed GetAttribute method and when we want to retrieve a custom attribute, we can use code that now looks like

CustomAttribute attribute = customType.GetType().GetAttribute<CustomAttribute>();

It might not look like a major change in the calling site, but we are now able to quickly and easily get a strongly typed attribute given an instance type.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Scott Dorman

Software Developer (Senior)

United States United States

Member

Follow on Twitter Follow on Twitter
Scott is a C# MVP and author who has been involved with computers in one way or another for as long as he can remember, but started professionally in 1993. He has worked at Fortune 500 companies and privately held start-ups focused on IT consulting where he gained experience in embedded systems design and software development to systems administration and database programming, and everything in between.
 
After spending 6 years as a systems administrator, Scott started developing eCommerce store fronts. Since 2001, he has worked on many different projects using .NET and C#. Although his primary focus right now is commercial software applications, he prefers building infrastructure components, reusable shared libraries and helping companies define, develop and automate process standards and guidelines.
 
Scott runs a software architecture-focused user group, speaks extensively, and contributes regularly to online communities such as The Code Project and StackOverflow, and is the Community Manager and Senior Editor for DotNetKicks.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralA variation on this theme that handles multiple attributes and caches results ... PinmemberHightechRider13:07 8 Jun '09  
Reflection can be slow, so if you are using this a lot you might want to cache the results. Also, it's possible that a class might have multiple attributes applied to it derived from the same base attribute type and you might want all of them. And finally, depending on how you use this, GetType() can move into the method simplifying things further.
 
Here's how I do it (for comparison) ...
 
private static Dictionary<Type, object[]> attributeCache = new Dictionary<Type, object[]>();
 
public static IEnumerable<T> GetAttributes<T>(this object obj) where T : Attribute
{
lock (attributeCache)
{
object[] attrs;
if (!attributeCache.ContainsKey(typeof(T)))
{
attrs = obj.GetType().GetCustomAttributes(false);
attributeCache.Add(typeof(T), attrs);
}
else
{
attrs = attributeCache[typeof(T)];
}
return attrs.OfType<T>();
}
}
 

Note: I also cache all the custom attributes on the first call assuming that if you ask for one you'll probably come back for the rest.
GeneralRe: A variation on this theme that handles multiple attributes and caches results ... PinmemberScott Dorman4:23 9 Jun '09  
GeneralRe: A variation on this theme that handles multiple attributes and caches results ... PinmemberHightechRider9:01 9 Jun '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120210.1 | Last Updated 8 Jun 2009
Article Copyright 2009 by Scott Dorman
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid