Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do attribute classes work?

Tags:

c#

attributes

My searches keep turning up only guides explaining how to use and apply attributes to a class. I want to learn how to create my own attribute classes and the mechanics of how they work.

How are attribute classes instantiated? Are they instantiated when the class they are applied to is instantiated? Is one instantiated for each class instantiated that it is applied to? E.g. if I apply the SerializableAttribute class to a MyData class, and I instantiate 5 MyData instances, will there be 5 instances of the SerializbleAttribute class created behind the scenes? Or is there just one instance shared between all of them?

How do attribute class instances access the class they are associated with? How does a SerializableAttribute class access the class it is applied to so that it can serialize it's data? Does it have some sort of SerializableAttribute.ThisIsTheInstanceIAmAppliedTo property? :) Or does it work in the reverse direction that whenever I serialize something, the Serialize function I pass the MyClass instance to will reflectively go through the Attributes and find the SerialiableAttribute instance?

like image 767
AaronLS Avatar asked Apr 20 '10 15:04

AaronLS


People also ask

How does attributes work in C#?

In C#, attributes are classes that inherit from the Attribute base class. Any class that inherits from Attribute can be used as a sort of "tag" on other pieces of code. For instance, there is an attribute called ObsoleteAttribute . This is used to signal that code is obsolete and shouldn't be used anymore.

What are attributes in dot net?

Attributes are used for adding metadata, such as compiler instruction and other information such as comments, description, methods and classes to a program. The . Net Framework provides two types of attributes: the pre-defined attributes and custom built attributes.

What are attribute classes?

The class attribute specifies one or more classnames for an element. The class attribute is mostly used to point to a class in a style sheet. However, it can also be used by a JavaScript (via the HTML DOM) to make changes to HTML elements with a specified class.


1 Answers

I haven't use attributes in my day-to-day work before, but I have read about them. Also I have done some tests, to back up what I'll say here. If I'm wrong in any place - feel free to tell me this :)

From what I know, attributes are not acting as regular classes. They aren't instantiated when you create an object that they are applied to, not one static instance, not 1 per each instance of the object. Neither do they access the class that they are applied to..

Instead they act like properties (attributes? :P ) of the class. Not like the .NET class properties, more like in the "one property of glass is transparency" kind of property. You can check which attributes are applied to a class from reflection, and then act on it accordingly. They are essentially metadata that is attached to the class definition, not the objects of that type.

You can try to get the list of attributes on a class, method, property, etc etc.. When you get the list of these attributes - this is where they will be instantiated. Then you can act on the data within these attributes.

E.g. the Linq tables, properties have attributes on them that define which table/column they refer to. But these classes don't use these attributes. Instead, the DataContext will check the attributes of these objects when it will convert linq expression trees to SQL code.

Now for some real examples.. I've ran these in LinqPad, so don't worry about the strange Dump() method. I've replaced it with Console.WriteLine to make the code easier to understand for the people who don't know about it :)

void Main() {     Console.WriteLine("before class constructor");     var test = new TestClass();     Console.WriteLine("after class constructor");      var attrs = Attribute.GetCustomAttributes(test.GetType()).Dump();     foreach(var attr in attrs)         if (attr is TestClassAttribute)             Console.WriteLine(attr.ToString()); }  public class TestClassAttribute : Attribute {     public TestClassAttribute()     {         DefaultDescription = "hello";         Console.WriteLine("I am here. I'm the attribute constructor!");     }     public String CustomDescription {get;set;}     public String DefaultDescription{get;set;}      public override String ToString()     {         return String.Format("Custom: {0}; Default: {1}", CustomDescription, DefaultDescription);     } }  [Serializable] [TestClass(CustomDescription="custm")] public class TestClass {     public int Foo {get;set;} } 

The console result of this method is:

before class constructor after class constructor I am here. I'm the attribute constructor! Custom: custm; Default: hello 

And the Attribute.GetCustomAttributes(test.GetType()) returns this array: (the table shows all available columns for all entries.. So no, the Serializable attribute does not have these properties :) ) LinqPad Attributes Array

Got any more questions? Feel free to ask!

UPD: I've seen you ask a question: why use them? As an example I'll tell you about the XML-RPC.NET library. You create your XML-RPC service class, with methods that will represent the xml-rpc methods. The main thing right now is: in XmlRpc the method names can have some special characters, like dots. So, you can have a flexlabs.ProcessTask() xml rpc method.

You would define this class as follows:

[XmlRpcMethod("flexlabs.ProcessTask")] public int ProcessTask_MyCustomName_BecauseILikeIt(); 

This allows me to name the method in the way I like it, while still using the public name as it has to be.

like image 198
Artiom Chilaru Avatar answered Sep 27 '22 22:09

Artiom Chilaru