14.5 Defining a New Custom Attribute

In addition to using the predefined attributes supplied by the .NET Framework, you can also create your own.

To create a custom attribute, use the following steps:

  1. Derive a class from System.Attribute or from a descendent of System.Attribute. By convention the class name should end with the word Attribute, although this isn't required.

  2. Provide the class with a public constructor. The parameters to the constructor define the positional parameters of the attribute and are mandatory when specifying the attribute on an element.

  3. Declare public-instance fields, public-instance read/write properties, or public-instance write-only properties to specify the named parameters of the attribute. Unlike positional parameters, these are optional when specifying the attribute on an element.

    The types that can be used for attribute constructor parameters and properties are bool, byte, char, double, float, int, long, short, string, object, the Type type, enum, or a one-dimensional array of all of these.

  4. Finally, as described in the preceding section, define what the attribute may be specified on using the AttributeUsage attribute.

Consider the following example of a custom attribute, CrossRefAttribute, which removes the limitation that the CLR metadata contains only information about statically linked types, but not dynamically linked ones.

// Xref.cs - cross-reference custom attribute
// compile with:
//   csc /t:library XRef.cs
using System;
[AttributeUsage(AttributeTargets.All, AllowMultiple=true)]
public class CrossRefAttribute : Attribute {
  Type   xref;
  string desc = "";
  public string Description { set { desc=value; } }
  public CrossRefAttribute(Type xref) { this.xref=xref; }
  public override string ToString( ) {
    string tmp = (desc.Length>0) ? " ("+desc+")" : "";
    return "CrossRef to "+xref.ToString( )+tmp;

From the attribute user's perspective, this attribute can be applied to any target multiple times (note the use of the AttributeUsage attribute to control this). CrossRefAttribute takes one mandatory positional parameter (namely the type to cross reference) and one optional named parameter (the description), and is used as follows:

[CrossRef(typeof(Bar), Description="Foos often hang around Bars")]
class Foo {...}

Essentially, this attribute embeds cross references to dynamically linked types (with optional descriptions) in the metadata. This information can then be retrieved at runtime by a class browser to present a more complete view of a type's dependencies.

    Part II: Programming with the .NET Framework
    Part IV: API Quick Reference