What Are Attributes in .Net

What are attributes in .NET?

Metadata. Data about your objects/methods/properties.

For example I might declare an Attribute called: DisplayOrder so I can easily control in what order properties should appear in the UI. I could then append it to a class and write some GUI components that extract the attributes and order the UI elements appropriately.

public class DisplayWrapper
{
private UnderlyingClass underlyingObject;

public DisplayWrapper(UnderlyingClass u)
{
underlyingObject = u;
}

[DisplayOrder(1)]
public int SomeInt
{
get
{
return underlyingObject .SomeInt;
}
}

[DisplayOrder(2)]
public DateTime SomeDate
{
get
{
return underlyingObject .SomeDate;
}
}
}

Thereby ensuring that SomeInt is always displayed before SomeDate when working with my custom GUI components.

However, you'll see them most commonly used outside of the direct coding environment. For example the Windows Designer uses them extensively so it knows how to deal with custom made objects. Using the BrowsableAttribute like so:

[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}

Tells the designer not to list this in the available properties in the Properties window at design time for example.

You could also use them for code-generation, pre-compile operations (such as Post-Sharp) or run-time operations such as Reflection.Emit.
For example, you could write a bit of code for profiling that transparently wrapped every single call your code makes and times it. You could "opt-out" of the timing via an attribute that you place on particular methods.

public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
bool time = true;
foreach (Attribute a in target.GetCustomAttributes())
{
if (a.GetType() is NoTimingAttribute)
{
time = false;
break;
}
}
if (time)
{
StopWatch stopWatch = new StopWatch();
stopWatch.Start();
targetMethod.Invoke(target, args);
stopWatch.Stop();
HandleTimingOutput(targetMethod, stopWatch.Duration);
}
else
{
targetMethod.Invoke(target, args);
}
}

Declaring them is easy, just make a class that inherits from Attribute.

public class DisplayOrderAttribute : Attribute
{
private int order;

public DisplayOrderAttribute(int order)
{
this.order = order;
}

public int Order
{
get { return order; }
}
}

And remember that when you use the attribute you can omit the suffix "attribute" the compiler will add that for you.

NOTE: Attributes don't do anything by themselves - there needs to be some other code that uses them. Sometimes that code has been written for you but sometimes you have to write it yourself. For example, the C# compiler cares about some and certain frameworks frameworks use some (e.g. NUnit looks for [TestFixture] on a class and [Test] on a test method when loading an assembly).

So when creating your own custom attribute be aware that it will not impact the behaviour of your code at all. You'll need to write the other part that checks attributes (via reflection) and act on them.

What Attributes really are?

They are simply metadata stored in the underlying definition (not instance) of the type. For example, if I do:

[Description("some text")]
public string Name {get;set;}

then the fact that DescriptionAttribute with a description constructor-parameter of "some text" is stored in the IL against the property Name. This has no impact on the cost of each instance, and it does nothing by itself. The only time this data is used is if code explicitly asks the runtime something like:

  • "what additional attribute metadata do you have against Name ?"
  • "does Name have a DescriptionAttribute ?"
  • "please construct me the DescriptionAttribute stored against Name, if one"

and then does something with the result.

CAVEAT: there are some attributes that are processed differently by the compiler and/or CLI, and are implemented differently. [Serializable], for example, becomes an IL type flag - not an IL attribute - but the runtime shims it so that the APIs report it as though it were the other.

Custom vs. non-custom attributes?

I don't know if the following has any relevance, but if you say

var a = typeof(string).Attributes;

you get a value of a flags enum type called TypeAttributes. Maybe these flags are the "non-custom" attributes of the type?

Is .Net attribute feature used at compile-time or run-time or both?

Attributes are output as metadata to the assembly at compile time. This meta data is then used at runtime via reflection - for example using GetCustomAttributes().

Some attributes are used by the compiler at compile time, too. For example the compiler looks at the AttributeUsageAttribute to determine if an attribute can be used for a specific object.



Related Topics



Leave a reply



Submit