Attributes can be applied to:
Attribute usage constraints enforce correct application of a custom attribute using the AttributeUsage attribute and the AttributeTargets enum. In other words, they define the targets for a custom attribute.
Guidelines for developing custom attributes:
Reflecting attributes:
You can specify multiple Conditional
attributes. They are combined with OR:
// A method with a Conditional attribute must have a return type of void. Also, it should not take any parameters. [Conditional("DEBUG"), Conditional("TRACE")] private void Check();
Examples of attribute definitions and permitted annotations:
// Attribute definition. public class TestAttribute : System.Attribute { } // Permitted annotation. [Test]
// Attribute definition that defines a positional parameter as a constructor parameter. public class TestAttribute : System.Attribute { public TestAttribute(int order) { this.order = order; } private int order; } // Permitted annotations. [Test(1)] [Test(12)] etc.
// Attribute definition that defines an optional named argument as a public read/write property: public class TestAttribute : System.Attribute { public bool Descending {get; set;} public TestAttribute(int order) { this.order = order; } private int order; } // Permitted annotations. [Test(1, Descending = true)] [Test(8)] etc.
Example: Define a custom attribute TestDescriptionAttribute and apply it to a class TestClass:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] public class TestDescriptionAttribute : System.Attribute { private string description; public string Description { get { return description; } set { description = value; } } public TestDescriptionAttribute() { } // This ctor takes a string as a parameter. As a result we are able to pass a string to // our attribute: [TestDescription("string")] public TestDescriptionAttribute(string desc) { description = desc; } } ... [TestDescription("This is class description.")] public class TestClass { }
Example: Check if a class TestClass has the Serializable attribute applied:
if (Attribute.IsDefined(typeof(TestClass), typeof(SerializableAttribute))) { // ... } ... [Serializable] class TestClass { }
Example: Obtain all attributes applied to the TestClass that are of type TestAttribute:
IEnumerable<CustomAttributeData> attrs = typeof(TestClass).GetType().GetCustomAttributes(TestAttribute); ... [Test] class TestClass { }
Example: Obtain an instance of ConditionalAttribute and examine its ConditionString property:
MethodInfo info = typeof(TestClass).GetMethod("TestMethod"); if (Attribute.IsDefined(info, typeof(ConditionalAttribute))) { ConditionalAttribute attr = (ConditionalAttribute)Attribute.GetCustomAttribute(info, typeof(ConditionalAttribute)); if (attr != null) Console.WriteLine(attr.ConditionString); // DEBUG } ... class TestClass { [Conditional("DEBUG")] public void TestMethod(string s) { } }
Example: Obtain assembly-level attributes AssemblyCompanyAttribute and AssemblyTitleAttribute:
string assemblyCompany = ((AssemblyCompanyAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyCompanyAttribute), false)).Company; string assemblyTitle = ((AssemblyTitleAttribute)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyTitleAttribute), false)).Title;