25.1 Creating a Custom Attribute Class Definition

 <  Day Day Up  >  

You want to define a new custom attribute.


Technique

Defining a custom attribute is simple: You define a class whose name should normally end in the string Attribute and which should be derived from the class System.Attribute . Listing 25.1 shows an example. For this sample, we assumed that we want to mark any code developed in house with some attribute. (You might perform this task for internal documentation purposes, for example, to distinguish in-house code from code that has been outsourced.)

Listing 25.1 A Basic Attribute Class
 public class InHouseAttribute : Attribute { } 

At the most basic level, that is literally all there is to it: the class defined in Listing 25.1, once compiled, is ready to be used to decorate any other code. Listing 25.2 shows the InHouse attribute being used to mark a class definition.

Listing 25.2 Using the Basic Attribute Class
 [InHouse()] class OurClass {         // etc. 

When you use attributes to decorate other code, it's permissible and customary to omit Attribute from the class name in the square brackets, as done here.

More realistically , you might want your attribute to have various values beyond simply being present or absent. Listing 25.3 shows a slightly more sophisticated custom attribute class that you could use to indicate in more detail who wrote some code. This attribute uses a bool to indicate whether the code was written in house and a string to provide a brief description of where the code originated. Two constructors are supplied, one accepting both parameters and one accepting just the bool , which effectively means that the description string is optional.

Listing 25.3 A More Complex Attribute Class That Takes Parameters
 public class ProgrammerTeamAttribute : Attribute {         private bool inHouse;         private string team;         public ProgrammerTeamAttribute(bool inHouse)                 : this(inHouse, null)         {         }         public ProgrammerTeamAttribute(bool inHouse, string team)         {                 this.inHouse = inHouse;                 this.team = team;         } } 

This class is also ready to be used, as shown in Listing 25.4.

Listing 25.4 Using the More Complex Attribute Class
 [ProgrammerTeam(true)] class OurClass {         [ProgrammerTeam(false, "We couldn't figure out how to implement TakeAHoliday so we contracted it out")]         public void TakeAHoliday()         {                 // etc.         } 

Although the ProgrammerTeam attribute defined in Listing 25.3 will work adequately, it does have one problem. There is no way for external code to access the values supplied to the constructor when the attribute is instantiated ”as, for example, would happen if some external code uses reflection to search code for attributes. For this reason, you normally add some public properties to allow access to these values, as shown in Listing 25.5.

Listing 25.5 An Attribute That Exposes its Fields via Public Properties
 public class ProgrammerTeamAttribute : Attribute {         private bool inHouse;         private string team;         public bool InHouse         {                 get                 {                         return inHouse;                 }         }         public string Team         {                 get                 {                         return team;                 }         }         public ProgrammerTeamAttribute(bool inHouse)                 : this(inHouse, null)         {         }         public ProgrammerTeamAttribute(bool inHouse, string team)         {                 this.inHouse = inHouse;                 this.team = team;         } } 

Listing 25.5 ensures that, if some other code uses reflection to examine a class that is decorated with the ProgrammerTeam attribute, then it can also retrieve the inHouse and team values using the corresponding public properties.

Comments

In general, whenever you decorate code with attributes, you must supply parameters that correspond to one of the constructors of the attribute class. Listings 25.3 and 25.5 supplied two constructors, effectively allowing an optional parameter. In general, however, it is conventional to implement optional parameters using properties, as described in Recipe 25.5, "Adding Optional Properties to Custom Attributes." You should also bear in mind that the classes defined in this recipe are minimal classes designed to implement just enough features to qualify as useful attributes. In real-world programming, it would not be considered good programming practice to define an attribute class without also explicitly specifying its usage, as described in the next recipe.

 <  Day Day Up  >  


Microsoft Visual C# .Net 2003
Microsoft Visual C *. NET 2003 development skills Daquan
ISBN: 7508427505
EAN: 2147483647
Year: 2003
Pages: 440

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net