Attributes in C#

C# Attributes and their uses

what are attributes?

Attributes enable you to embed information about a type or method in the metadata which describes that type or method.

You typically want to use attributes to describe facts about the mechanism of the type or method rather than the meaning of the type or method. For example, suppose you have a type Employee. A fact about the meaning of Employee is that it is a kind of Person, that an Employee has a Manager, and so on. A fact about the mechanism of Employee is that it can be the target of data binding, or it can be serialized to disk, or whatever. An employee cannot be serialized to disk, but the class Employee can be. Attributes let you separate information about the technical details from the semantic model.

Is there a way to create my own attributes?

Yes. Create a class which extends Attribute. By convention you want to name it "FooAttribute". If you do so you can use either the [Foo] syntax or the [FooAttribute] syntax at your discretion.

How can I tell if fields/methods/classes/whatever have particular attributes or what values are set in those attributes?

Use the GetCustomAttributes method on the reflection objects.

Where should I read for more information?

Start with the attributes tutorial:

http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

And then read all of chapter 17 of the C# specification.

C# attributes and methods

I have written a small demo application that should help you to complete your logic. Overall, of course, it still has room for improvement, but it works:

using System;
using System.Linq;
using System.Reflection;

namespace DemoApp
{
class Program
{
static void Main(string[] args)
{
string command = Console.ReadLine().Trim();

LogicProvider provider = new LogicProvider();
MethodInfo method = provider.GetType().GetMethods().FirstOrDefault((item) => item.GetCustomAttribute<CommandAttribute>().Identifier == command);
method?.Invoke(provider, null);
}
}

public class LogicProvider
{
[Command("DemoCommand")]
public void MyMethod()
{
Console.WriteLine("Here");
}
}

public class CommandAttribute : Attribute
{
public CommandAttribute(string identifier)
{
this.Identifier = identifier;
}

public string Identifier { get; } = null;
}
}

If DemoCommand is entered in the console, then a search is made in the LogicProvider for a matching method. If there is a match, it is executed.

The whole thing also works with methods that have parameters. In the case of method?.Invoke(), this can then be specified.

What is the difference between C# Attribute and C# Static Field?

DEFINITION

A static data field or property is a variable encapsulated in the abstraction of a class definition.

Attribute is a decoration, a parameter, not a data itself, added to a class type or to a member field, property or method.

An attribute itself does nothing and represent nothing in terms of data or code : it is a conceptual artifact, added to the code, that can be used by the code, by some method, to change the behavior.

Attribute is a class that can contains data and methods to manage some behaviors of a class.

Attributes allows to segregate more between abstraction and encapsulation.

They allow to better refine design as well as to specialize behaviors at coding time while allowing generalization.

EXAMPLE

Consider this class:

public class LogFile
{
static public List<LogFile> LogFiles { get; private set; }
}

Here it is a static list that contains all log files instantiated.

It is a data, a variable, something concrete and tangible, directly usable by internal and external code.

Here is an example of attribute usage:

[LogFileStorage(LogFilePath.User)]
public class LogFile
{
}

Here it is a code tag added to the class definition at the code level, that can't be changed, unless using reflexion, and that can be used by the logfile manager class to define a save path like in a temp folder or the user app folder or a runtime defined path (in a different and detached way from a constant or a default value).

So in this example, the log file save method will check the class attributes to know where to save it.

An attribute lets coders to parameterize class they define as well as child class and any class member.

A classical example is the Serializable attribute:

https://learn.microsoft.com/dotnet/api/system.serializableattribute

TUTORIALS

https://www.tutorialspoint.com/csharp/csharp_attributes.htm

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/attributes/

https://learn.microsoft.com/dotnet/csharp/tutorials/attributes

https://www.tutorialspoint.com/csharp/csharp_encapsulation.htm

https://www.c-sharpcorner.com/UploadFile/mkagrahari/introduction-to-object-oriented-programming-concepts-in-C-Sharp/

Understanding Attributes in c#

I don't see any object being created here?

Well, there is. When you request the attributes from AnyClass using reflection, it creates a new instance of the attribute with the specified parameters.

Actually the attribute will be created just like any other class, just the syntax is different to specify an attribute.

Note that the attribute will not be called automatically on the constructor of AnyClass!

Type t = typeof(AnyClass);
HelpAttribute[] attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
.Cast<HelpAttribute>()
.ToArray(); // on this line the attribute is instantiated

Console.WriteLine(attributes.FirstOrDefault()?.Description);

Understanding C# attributes

Attributes are additional metadata, added to type and gives additional information about it. There are a couple of points, where you should use attributes, reflection and serialization are main of them. This thread and this article will help you

What syntax is allowed when applying C# attributes?

AFAIK, named parameters only permit integral types. Unfortunately i do not have a reference to back this up, I only learnt it through my own experimentation.

When trying to use object initialisers, I got this error from the compiler:

An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

Although this documentation is a few years old, it has the reference information I was looking for:

Attribute parameters are restricted to constant values of the
following types:

  • Simple types (bool, byte, char, short, int, long, float, and double)
  • string
  • System.Type
  • enums
  • object (The argument to an attribute parameter of type object must be a constant value of one of the above types.) One-dimensional
    arrays of any of the above types

So this works:

//Test attribute class
[AttributeUsage(AttributeTargets.All)]
internal class TestAttribute : Attribute
{
public int[] Something { get; set; }
}

//Using an array initialiser - an array of integers
[TestAttribute(Something = new int[]{1, 2, 3, 4, 5})]
public abstract class Something

Whereas this wouldn't:

//Test person class
internal class Person
{
public string Name { get; set; }

public Person(string name)
{
this.Name = name;
}
}

//Test attribute class
[AttributeUsage(AttributeTargets.All)]
internal class TestAttribute : Attribute
{
public IEnumerable<Person> Something { get; set; }
}

//This won't work as Person is not an integral type
[TestAttribute(Something = new Person[]{new Person("James")})]

EDIT: just to elaborate, attributes form part of the metadata for constructs they are applied to (within the generated IL), thus the members of the attribute class must be determined at compile time; hence the restriction on attribute parameters to constant values.

When should I use attribute in C#?

In the .NET Framework, attributes can be used for many reasons -- like

  • Defining which classes are
    serializable

  • Choosing which methods are exposed in
    a Web service

Attributes allow us to add descriptions to classes, properties, and methods at design time that can then be examined at runtime via reflection.

Consider this example:

Say you have a class which has a method from older version which is still in use for any reason and now you have come up with a new version of the class which makes fantastic use of Generic List and LINQ and has a new method for similar purpose. You would like developers to prefer the new one provided in the later version of your library. How will you do that ? One way is to write in the documentation. A better way is to use attribute as follow.

public class AccountsManager
{
[Obsolete("prefer GetAccountsList", true)]
static Account[] GetAccounts( ) { }
static List<Account> GetAccountsList( ) { }
}

If an obsolete method is used when the program is compiled, the developer gets this info and decides accordingly.

AccountManager.GetAccounts() is obsolete:
prefer GetAccountsList

We may also create and add Custom Attributes as per requirements.

Reference :

  • Using Attributes in C#

Hope this helps



Related Topics



Leave a reply



Submit