views:

526

answers:

7

I don't really understand attributes. I've read all kinds of books & posts on them, but I just don't get it.

Since I don't understand them, I also don't understand how to effectively use them.

1) Can you give me a good definition of what an attribute is & what it's used for?

2) Can you give me a good code example in C# of how to make and consume a custom attribute?

+1  A: 

Have a lot at e.g. log4PostSharp. They use attributes to introduce AOP behaviour.

That's an attribute I used once, to give properties a unit (like seconds, meter, ...)

[AttributeUsage( AttributeTargets.Property )]
public sealed class UnitAttribute : Attribute
{
  public UnitAttribute( Unit unit )
  {
    Unit = unit;
  }

  public Unit Unit { get; private set; }
}

It was used on properties, like this:

[Unit( Unit.Meter )]
public float Distance { get; set; }

You can later retrieve the attribute to show it on the GUI.

tanascius
+8  A: 

I could give you an example but it would pale in comparison to this fine article:

Defining and Using Custom Attribute Classes in C#

The complex, component-style development that businesses expect out of modern software developers requires greater design flexibility than the design methodologies of the past. Microsoft's .NET Framework makes extensive use of attributes to provide added functionality through what is known as "declarative" programming. Attributes enhance flexibility in software systems because they promote loose coupling of functionality. Because you can create your own custom attribute classes and then act upon them, you can leverage the loose coupling power of attributes for your own purposes.

Andrew Hare
+2  A: 

An attribute is used to provide meta data about any member (fields, class etc).

You can create them by inheriting from Attribute, and consume them by using the Attribute.GetCustomAttribute method.

An example of a default attribute is the PrincipalPermissionAttribute which only allows authenticated users to access certain resources. For example:

[PrincipalPermission (SecurityAction.Demand, Role="Supervisor")]
public class DoTheThingPage : Page
{
    ////
}

In this example, we have an ASP.NET page that can only be viewed by an authenticated user that belongs to the 'Supervisor' role.

(This attribute is automatically read by the security sub-system in ASP.NET)

Also note that the 'Attribute' part of the class name wasn't used, it's a convention within .NET.

Kieron
+1  A: 

We have a requirement to display Enum Values in a dropdown in a specific sort order. We implemented using Custom Attributes.

[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field, AllowMultiple = false)]
public class EnumSortAttribute : Attribute
{
    public int SortOrder;
    public bool SortByDescription;
}

[EnumSort(SortByDescription=true)]
public enum EnumSortByDescription
{
    [Description("enO")]
    One = 1,
    [Description("2")]
    Two = 2,
    Three = 3,
    [Description("rouF")]
    Four = 4
}

public enum EnumCustomSortOrder
{
    [EnumSort(SortOrder = 3)]
    One = 1,
    [EnumSort(SortOrder = 1)]
    Two = 2,
    [EnumSort(SortOrder = 2)]
    Three = 3
}
Vasu Balakrishnan
+1  A: 

Say you've got a class with a series of properties that you are going to walk through using reflection. Any that are strings may need to be validated to check they are not longer than a certain amount.

You could then create a textLength attribute, with a default integer constructor and integer property/field. You could then read your attribute on each string property in your class and compare the length of the property value to the number specified in the attribute.

Code:

public class TextLengthAttribute : Attribute
{
    private int length;
    public int Length { get { retrun length; } set { length = value; } }

    public textLengthAttribute(int num) { this.length = num ; }
}

public class MyClass
{

    [TextLength(10)]
    public string Property1;
    [TextLength(20)]
    public string Property2;
}

public class ClassReader
{
     public static void Main()
     {
          MyClass example = MyClass.GetTestData();

          PropertyInfo[] props = typeof(MyClass).GetProperties();
          foreach (PropertyInfo prop in props)
          {
               if (prop.ValueType == typeof(String) 
               {
                    TextLengthAttribute[] atts = 
                      (TextLengthAttribute)[]prop.GetCustomAttributes(
                           typeof(TextLengthAttribute), false);
                    if (prop.GetValue(example, null).ToString().Length > 
                         atts[0].Length) 
                        throw new Exception(prop.name + " was too long");
               }
          }
     }
}

Note: untested

ck
+1  A: 

Attribute is just a way to add additional information (metadata) to the class, struct or some member. This meta-data could be retrieved by other code in order to make some decisions.

Simplest example is SerializableAttribute from the .NET. It indicates that the class could be serialized by a BinaryFormatter later on.

Here's another example - we could mark some classes in our code with ImmutableAttribute to indicate that they don't have any mutable fields and are OK for multi-threaded operations:

[Immutable]
public sealed class ProcessingMessage
{
    //... some code that should be thread-safe

}

Then, we could create a unit test that finds all classes with the attribute and ensures that they are immutable indeed:

[Test]
public void Immutable_Types_Should_Be_Immutable()
{
  var decorated = GlobalSetup.Types
    .Where(t => t.Has<ImmutableAttribute>());

  foreach (var type in decorated)
  {
    var count = type.GetAllFields().Count(f => !f.IsInitOnly && !f.IsStatic);
    Assert.AreEqual(0, count, "Type {0} should be immutable", type);
  }
}
Rinat Abdullin