C# Attributes Basics
A simple guide to C# attributes uses. Attributes are a powerful method of associating metadata or declarative information with code.
Join the DZone community and get the full member experience.Join For Free
Attributes are a powerful method of associating metadata or declarative information with code.
You can think of attributes as adding tags/notes to code:
There are various uses of attributes, such as:
- Add meta-data to code elements.
- Configure conditional compilation.
- Decorate code as obsolete.
- Data validation rules/error messages.
- Control serialization/deserialization.
- Azure Function bindings.
Attributes and Reflection
Attributes and Reflections are two separate but strongly related topics.
Reflection allows you to dynamically find out at runtime what methods and properties etc., are available on your types.
Attributes let you attach additional metadata to your code, and the connection with reflection is that you can use reflection to read that metadata.
Attributes are compiled into the resulting assemblies. Attributes are applied at compile-time, not at runtime.
Next, let's see some code examples. All the example's source code is available on this git repo.
Attribute Basic Example – Built-in Attributes
Let's see a basic example of built-in attributes provided by the framework itself.
You can see the Key attribute is applied to the Id property.
And here is the reflection code which accesses this attribute:
Don’t worry if this code is unclear to you yet; we will go into details later in the post.
Here is another built-in attribute, Obsolete, applied to the Device class:
An Obsolete attribute is a declarative tag used while declaring a type or a member of a type to indicate that it should no longer be used.
With this attribute applied, if we now try to use this type (Device class) in our program, Visual Studio will give us the following warning:
So, this is another common use of the attribute, mark code obsolete.
So far, we’ve applied attributes to both class and its properties. Later we will see that we can apply attributes to a wide range of targets.
Attribute Example – Friendly Text for Enums
Let’s see an example use of Attributes.
Following is the updated code of the Device Class. We’ve defined the DeviceType Enum and used it in the Device class:
And here is the console output from the program, which outputs a string representation of the DeviceType Enum:
Now, let's say that we want human-friendly readable text instead of the string representation of Enum, e.g., “Virtual Device” instead of “VirtualDevice.”
Here is how we can do this via attributes:
- First, create an attribute to add human-friendly text to enum items.
- Then, use reflection to extract that text to display friendly text.
Create a Custom Attribute
The following code shows how to create a custom attribute for our requirement:
As you can see, that our custom attribute is just a simple class that inherits from the built-in Attribute type, with one property to hold the friendly text, which is set via the constructor. This follows a naming convention that says you need to suffix your custom attribute with Attribute.
Notice the use of AttributeUsage applied to restrict it to be applied only to fields (enum values are internally implemented as static fields). AttributeUsage is another built-in attribute provided by the .NET framework itself.
Apply Custom Attribute
The following code shows that the FriendlyText custom attribute is applied to enum items:
Extraction via Reflection
So, we have declared and applied the custom attribute (FriendlyText). This is the first half of the solution.
The other half is to extract that custom attribute via reflection and use it in our code. For example, the following code does this part:
And we can now use it in our code as needed:
Here is the console output of the usage:
Let's see another example of a custom attribute next.
Attribute Example – Attribute on a Type
For this example, we have the following setup:
Here is the C# implementation of this domain model. Most of the code is self-explanatory, here Vehicle class is acting as a base class, and other classes (Car, Truck, FlyingCar) are derived classes with few of their own properties:
In the main method, we have the following simple usage:
Here, in our domain, we might have vehicles that are just for testing/prototype purposes, and those should not be used in our application as actual vehicles. To facilitates this requirement, we can mark those types which can be treated as actual vehicles(e.g., can be included in reports, can be sold, etc.).
We can achieve this by creating a custom attribute as follows:
Now, we can mark desired code with this attribute as shown below:
At this point, the attribute is defined and applied.
Next, we need to test whether a given type has that attribute applied, and this is where reflection comes in:
We can now simply use this helper method as shown below:
This is also a very common use of attributes to mark your types for certain conditions.
Attribute Example – Attribute on a Type
Here is another example of applying an attribute to a type:
Target Class to Apply Attribute
Following is a simple company attribute to apply to Server.
Apply Custom Attribute
Note: server.GetType and typeof(Sever) result same. typeof() is used when you know the type upfront.
Attribute Example – Attribute on a Type and Properties
Now, for this example, I created a custom attribute (InfoAttribute), which can be applied to both a Type (e.g., Server) or type one or more Properties. This attribute will hold some help/info text.
The following are the components:
Here is the attribute applied to type and a few of its properties:
And here are the calling code and output:
You can check the source code available from this git repository for more details.
I will not go into details, but ActionFilters are very common to use in .NET API development.
An Action filter is an attribute that you can apply to a controller action — or an entire controller — that modifies the way in which the action is executed.
C# Attributes are a very powerful and useful feature. They allow us to add meta-data to our code, and we can use Reflection to read that metadata. Furthermore, attributes are applied at compile-time.
Attributes can be applied to a wide variety of code elements such as classes, fields, attributes, properties, methods, etc. To see a list of common targets and more information about C# attributes, you can visit the official documentation on this link.
Let me know if you have some comments or questions. Till next time, Happy coding.
Published at DZone with permission of Jawad Hasan Shani. See the original article here.
Opinions expressed by DZone contributors are their own.