Attributes and Reflection

Attributes provide a powerful way to associate metadata (declarative information) with code.

After association, query the attribute at run time through using reflection. Attributes have four important properties:

  1. Attributes add information about types defined in an application.
  2. One or more attributes can be applied to full assemblies, modules, or small elements of an application, e.g., classes and properties.
  3. Attributes take arguments like methods and properties.
  4. Reflection enables an application to examine its own metadata or that of other applications.

PARAMETERS

Attribute parameters are typically positional, named, or unnamed. Positional parameters must appear in the correct order and cannot be omitted. Named parameters can be omitted and have no order. Always specify positional parameters first.

[DllImport("user489.dll")]
[DllImport("user489.dll", SetLastError=true, ExactSpelling=true)]
[DllImport("user489.dll", ExactSpelling=true, SetLastError=true)]

TARGETS

An attribute's target refers to the target of application, e.g., a class or method. Its target can be specified, and the default target is the element it precedes. The syntax for specification follows:

[target : attribute-list]

Review a list of possible target values below:

Name Area of Use
assembly Full assembly
module Current assembly module
field The field within a struct or class
event Event
method Method or property accessors(get and set)
param Method parameters or parameters of set property accessor
property Property
return Method return value, property indexer return value, or get property accessor return value
type Delegate, class, enum, interface, or struct

Review an example of target use:

using System;
using System.Reflection;
[assembly: ComponentNomenclatureAttribute("Build 4.2”)]
[module: CodeCompliant(false)]

Review an example of applying attributes to methods, method return values, and method parameters:

//default (method)
[AnAttr]
int MethodOne()
{
	return 0;
}
//method
[method: AnAttr]
int MethodTwo()
{
	return 0;
}
//return value
[return: AnAttr]
int MethodThree()
{
	return 0;
}

Attributes prove useful for a wide variety of tasks, review a selection of uses below:

  1. Describe an assembly in terms of its version, trademark, description, or title.
  2. Describe class members serialized for persistence.
  3. Detail security characteristics.
  4. Gather information about a method's caller.
  5. Describe COM properties for interfaces, methods, and classes.

REFLECTION

Reflection delivers objects describing modules, assemblies, and types. Reflection dynamically creates instances of a type, binds types to an existing object, or gathers the type from an existing object for invocation of its methods; or access to its properties and fields. When using attributes, reflection allows access to them. Review an example of reflection below which uses the static GetType method(inherited from the Object base class) to grab a variable's type:

int x = 23;
System.Type type = x.GetType();
System.Console.WriteLine(type);

This example uses reflection to grab the loaded assembly's full name:

System.Reflection.Assembly info = typeof(System.Int32).Assembly;
System.Console.WriteLine(info);

This example uses reflection to access attributes:

class TheMainClass
{
	public static void Main()
	{
		System.Reflection.MemberInfo info = typeof(AClass);
		object[] attributes = info.GetCustomAttributes(true);
		for (int i = 0; i < attributes.Length; i ++)
		{
			System.Console.WriteLine(attributes[i]);
		}
	}
}

Reflection proves most useful in the scenarios that follow:

  1. Attributes must be accessed in an application's metadata.
  2. Types within an assembly must be examined and instantiated.
  3. New types must be built at runtime.
  4. Binding is performed late, and method access must be performed on types spawned at run time.