The examples I provide in this article are involved in run-time activities. But Binaries (assemblies) aren't just for run-time. In .NET, the metadata you describe isn't limited to being available only at runtime. You can query the metadata at any time
after you've compiled an assembly.
Think about some design-time possibilities. The open nature of the IDE in Visual Studio.NET allows you to create tools (using .NET languages) that facilitate development and design (wizards, builders, etc.) Thus, one module's run-time environment (the IDE tool) is another module's design-time environment (the source code being developed). This presents a fine opportunity to implement some custom attributes. You could allow the IDE tool to reflect and then act upon the source classes/types you develop. Unfortunately, due to the additional subject of the IDE tool code, exploring such an example is beyond the scope of a single article.
The standard .NET attributes contain a similar example. When a developer creates custom controls to include in the Toolbox of the Visual Studio .NET IDE, they have attributes available to them to indicate how to handle the control in the property sheet. Table 1
lists and describes the four standard .NET attributes that the property sheet uses.
Table 1: Standard .NET attributes that the property sheet uses at design-time in the Visual Studio .NET IDE.
Specifies the class used to implement design-time services for a component.
Specifies which property to indicate as the default property for a component in the property sheet.
Specifies the category in which the property will be displayed in the property sheet.
Specifies the description to display in the property sheet for a property.
These property sheet-related attributes make it clear that you can use attributes and their values in the design-time as well as in the run-time environment.
Custom Attributes vs. Class Properties
Obvious similarities exist between attributes and regular member properties of a class. This can make it difficult to decide when and where you might want to utilize a custom attribute class. Developers commonly refer to properties of a class and their values as being "attributes" themselves, so what really is the difference between properties and attributes?
An attribute takes the same "shape and form" as a property when you define it, but you can attach it to all manner of different assembly level typesnot just Classes. Table 2
lists all the assembly level types that you can apply attributes to.
Table 2: .NET assembly level types that you can apply attributes to.
Let's pick one item from the list as an example. You can apply an attribute to a parameter, which is a little bit like adding a property
to a parametera very novel and powerful idea indeed, because you just can't do that with class member properties. This emphasizes the biggest way in which attributes and properties are different, because properties are simply always going to be members of a classthey can't be associated with a parameter or any number of other types listed in Table 2
other than Class.
Member properties of a class are also limited in another way in which attributes are not. By definition, a member property is tied to a specific class. That member property can only ever be used through an instance or subclass instance of the class on which the property was defined. On the other hand, you can attach/apply attributes anywhere! The only requirement is that the assembly type the attribute is being attached to matches the validon
definition in the custom attribute. I'll talk more about the validon
property of custom attribute classes in the next section. This characteristic of attributes helps to promote the loose coupling that is so helpful in component-style development.
Another difference between properties and attributes relates to the values you can store in each of them. The values of member properties are instance values and can be changed at run-time. However, in the case of attributes, you set values at design time (in source code) and then compile the attributes (and their values) directly into the metadata contained in an assembly. After that point you cannot change the values of the attributesyou've essentially turned the values of the attributes into hard-coded, real-only data.
Consider this when you attach an attribute. If you attach an attribute to a class definition for example, every instance
of the class will have the same values assigned to the attribute regardless of how many objects of this class type you instantiate. You cannot attach an attribute to an instance
of a class. You may only attach an attribute to a Type/Class definition.