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:
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. 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. 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. 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.
|