25.5 Adding Optional Properties to Custom Attributes

 <  Day Day Up  >  

You want to allow optional properties to be passed to custom attributes using the <property>=<value> syntax in the decoration line.


Technique

The technique is to define a public property in the attribute class with the given name and to ensure that the property has a set accessor. Suppose, for example, that as part of a scheme to link classes to fields in a database, you defined a Field attribute, and you want to be able to allow classes that use this attribute to optionally indicate a maximum value. Listing 25.12 shows how you can do so.

Listing 25.12 An Attribute with an Optional Property
 [AttributeUsage(AttributeTargets.Class)] public class FieldAttribute : Attribute {         private int maxValue;         public int MaxValue         {                 get                 {                         return maxValue;                 }                 set                 {                         maxValue = value;                 }         } } 

The MaxValue property in Listing 25.12 is optional only in the sense that when you decorate a class with this attribute, you are free to specify or not specify a value for the property. The property is always present in the attribute but has a default value of zero if not explicitly specified. Listing 25.13 illustrates both possibilities.

Listing 25.13 Using an Attribute That Has an Optional Property
 // this class supplies a MaxValue of 100 with the attribute [FieldAttribute(MaxValue = 100)] class PercentSuccessfulSales {         // implementation here } // this class is also decorated with the attribute, but does not // specify a value for MaxValue. // MaxValue in this attribute will retain its default value of zero [FieldAttribute()] class NumberOfVisits {         // implementation here } 

Bear in mind that, despite the suggestive name of the MaxValue property, all we are doing in this code is supplying information about the class that is available to be inspected using reflection. This code does not actually enforce any maximum values in any database. If you want to enforce a maximum field value based on this sample, you have to separately write some code that inspects the state of the attribute and that provides appropriate enforcement. Recipe 25.7, "Displaying Assembly Custom Attribute Information Using Reflection," explains how to examine attribute state.

The syntax for decorating a class with a custom attribute is exactly the same as that for an attribute that Microsoft has defined. In particular, when using the attribute, you must declare any optional property values after any values to be passed to a constructor. For example, suppose we modify Listing 25.13 so that the FieldAttribute constructor takes one parameter.

Listing 25.14 An Attribute with a One-Parameter Constructor and an Optional Property
 [AttributeUsage(AttributeTargets.Class)] public class FieldAttribute : Attribute {         public FieldAttribute(string tableName)         {                 this.tableName = tableName;         }         string tableName;         private int maxValue;         public int MaxValue         {                 get                 {                         return maxValue;                 }                 set                 {                         maxValue = value;                 }         } } 

The possible ways of decorating a class with this attribute appear in Listing 25.15.

Listing 25.15 Using an Attribute That Has a One-Parameter Constructor and an Optional Property
 // this class supplies a MaxValue of 100 with the attribute [FieldAttribute("Sales", MaxValue = 100)] class PercentSuccessfulSales {         // implementation here } // this class is also decorated with the attribute, // but does not specify a value for MaxValue. // MaxValue in this attribute will retain its default value of zero [FieldAttribute("SalespersonVisits")] class NumberOfVisits {         // implementation here } 

Comments

The examples in this recipe simply implement the MaxValue property as a wrapper around a field called maxValue . You can, of course, write whatever code you want in the get and set accessors of the property, but for an attribute property, it would be unusual to implement anything substantially different from simply wrapping a field.

You should also bear in mind that the get and set accessors of an attribute property have slightly different special roles:

  • The main purpose of the set accessor is to let you specify the property value when an item of code is decorated with the attribute.

  • The main purpose of the get accessor is to allow the value to be examined if the attribute is examined later on using reflection.

You are free to omit either accessor if you feel it is appropriate. However, if you omit the set accessor of an attribute property, then it will not be possible for code to set the property using the syntax style [MyCustomAttribute(<PropertyName>=<value>)] when the attribute is used. On the other hand, if you omit the get accessor, it will not be possible for code that uses reflection to instantiate the attribute to examine the value of the property.

 <  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