Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Attributes in C #

2025-01-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly shows you "how to use Attributes in C#", the content is easy to understand, clear, hope to help you solve doubts, the following let the editor lead you to study and learn "how to use Attributes in C#" this article.

Introduction of C # Attributes

Attributes is a new description, and we can use attributes to define design-time information (such as help files, URL of documents) and attributes to define run-time information (for example, associate elements in XML with member fields of a class). We can also use attributes to create a "self-describing" component.

C # Attributes definition

The definition in MSDN is as follows (ms-help://MS.MSDNQTR.2002APR.1033/csspec/html/vclrfcsharpspec_17_2.htm)

"An attribute is a piece of additional declarative information that is specified for a declaration."

Use predefined Attributes

There is already a small group of predefined attributes in c #. Before we learn how to create a custom attributes, let's take a look at the predefined attributes used in our code.

Using System; public class AnyClass {[Obsolete ("Don't use Old method, use New method", true)] static void Old () {} static void New () {} public static void Main () {Old ();}

Take a closer look at the example, where we use the "Obsolete" attribute, which marks a language element that should no longer be used. The * * arguments to this attribute are of type string, which explains why the element is abandoned and what element we should use to replace it. In practice, we can write any other text instead of this text. The second parameter is to tell the compiler to treat the identified element as an error, which means that the compiler will generate a warning.

When we try to compile the above program, we get the following error:

AnyClass.Old ()'is obsolete: 'Don't use Old method, use New method'

Develop a custom Attributes

Now we are about to learn how to develop a custom attributes. Here is a little prescription with which we can learn to create a custom attributes.

In C #, our attribute classes are all derived from System.Attribute classes (A class that derives from the abstract class System.Attribute, whether directly or indirectly, is an attribute class. The declaration of an attribute class defines a new kind of attribute that can be placed on a declaration), let's just do it.

Using System; public class HelpAttribute: Attribute {}

Believe me or not, we have created a custom attribute. You can now use it to decorate our classes, just as we do with obsolete attribute.

[Help ()] public class AnyClass {}

Note: by convention, we use the suffix "Attribute" for the attribute class name, however, when we bind attribute to a language element, we do not include the "Attribute" suffix. The compiler first looks for the attribute in the inherited class of System.Attribute, and if it does not find it, the compiler appends "Attribute" to the name of the attribute and then looks for it.

But so far, the attribute is of no use. In order to make it useful, let's add something to it.

Using System; public class HelpAttribute: Attribute {public HelpAttribute (String Descrition_in) {this.description = Description_in;} protected String description; public String Description {get {return this.description } [Help ("this is a do-nothing class")] public class AnyClass {}

In the above example, we added an attribute to the attribute class, which we will query at run time in the * * section.

Define or control the use of custom Attribute

The AttributeUsage class is another predefined class, which will help us control the use of our custom attribute, that is, we can define an attributes for the custom attribute class.

It describes how a custom attribute class can be used.

AttributeUsage provides three properties, which we can place on our custom attribute class. The * features are:

ValidOn

With this attribute, we can specify which language elements our custom attribute can be placed on. This set of language elements on which we can place custom attribute classes are placed in the enumerator AttributeTargets. We can use bitwise. [AttributeUsage ((AttributeTargets) 4, AllowMultiple = false, Inherited = false)], 4 means "class" element, others such as 1 for "assembly", 16383 for "all", etc.) or "." The operator binds several AttributeTargets values. (translator's note: default is AttributeTargets.All)

AllowMultiple

This attribute indicates that our custom attribte can be used multiple times on the same language element. (translator's note: this attribute is of type bool, and the default value is false, which means that the custom attribute can only be used once on the same language element)

Inherited

We can use this property to control the inheritance rules of our custom attribute class. This attribute identifies whether our custom attribute can be inherited by a derived class. (translator's note: this attribute is of type bool, and the default value is false, which means it cannot be inherited)

Let's do something practical. We will put AttributeUsage attribute on our help attribute and with its help, we will control the use of help attribute.

Using System; [AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public class HelpAttribute: Attribute {public HelpAttribute (String Description_in) {this.description = Description_in;} protected String description; public String Description {get {return this.description;}

First, we pay attention to AttributeTargets.Class. It states that the help attribute can only be placed on top of the language element "class". This means that the following code will generate an error.

AnyClass.cs: Attribute 'Help' is not valid on this declaration type.

It is valid on 'class' declarations only.

Now try to bind it to the method.

[Help ("this is a do-nothing class")] public class AnyClass {[Help ("this is a do-nothing method")] / / error public void AnyMethod () {}}

We can use AttributeTargets.All to allow Help attribute to be placed on any predefined language element, which is as follows:

[Help ("this is a do-nothing class")] [Help ("it contains a do-nothing method")] public class AnyClass {[Help ("this is a do-nothing method")] / / error public void AnyMethod () {}}

It produces a compilation error:

AnyClass.cs: Duplicate 'Help' attribute

Ok! Now it's time to talk about the attribute, "Inherited", indicating whether the derived class inherits the attribute when the attribute is placed on top of a base class. If the "Inherited" bound to an attribute class is set to true, the attribute will be inherited, while if the "Inherited" bound to an attribute class is set to false or undefined, then the attribute will not be inherited.

Let's assume that there is a class relationship as follows.

[Help ("BaseClass")] public class Base {} public class Derive: Base {}

We have four possible bindings:

* *

If we query the help attribute in the derived class (we'll learn later how to query attributes at run time), we won't be able to query because "Inherited" is set to false.

The second case

The second case is no different because its "Inherited" is also set to false.

The third situation

To explain the third and fourth cases, let's bind the same attribute for derived classes as well.

[Help ("BaseClass")] public class Base {} [Help ("DeriveClass")] public class Derive: Base {}

Now that we query the relevant help attribute, we will only get the attribute of the derived class. Why is this because although help attribute is allowed to be inherited, it cannot be used on the same language element multiple times, so the help attribute in the base class is overridden by the help attribute of the derived class.

The fourth situation

In the fourth case, when we query the help attribute of a derived class, we get two attributes, of course, because help attribute allows both inheritance and multiple uses on the same language element.

Note: AttributeUsage attribute is valid only for attriubte classes that are derived from System.Attribute and are bound to the value that both AllowMultiple and Inherited of this attriubte class are false.

Optional parameter vs. Named parameter

Optional parameters are parameters of the attribute class constructor. They are mandatory and must provide a value each time the attribute binds to a language element. Named parameters, on the other hand, are really optional parameters, not those in the attribute constructor.

For a more detailed explanation, let's add additional properties to the Help class.

[AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false) public class HelpAttribute: Attribute {public HelpAttribute (String Description_in) {this.description = Description_in; this.verion = "No Version is defined for this class";} protected String description; public String Description {get {return this.description }} protected String version; public String Version {get {return this.version;} / / if we ever want our attribute user to set this property, / / we must specify set method for it set {this.verion = value } [Help ("This is Class1")] public class Class1 {} [Help ("This is Class2", Version = "1.0")] public class Class2 {} [Help ("This is Class3", Version = "2.0", Description = "This is do-nothing class")] public class Class3 {}

When we query Help attribute for its properties in Class1, we get:

Help.Description: This is Class1

Help.Version: No Version is defined for this class

Because we don't have any values defined for the Version property, the values we set in the constructor are queried. If no value is defined, a default value of that type is assigned (for example, if it is int, the default value is 0).

Now, the result of querying Class2 is:

Help.Description: This is Class2

Help.Version: 1.0

Instead of using multiple constructors for optional parameters, we should use named parameters instead. We call them named because when we provide values for them in the constructor, we have to name them. For example, in the second class, we define Help as follows.

[Help ("This is Class2", Version = "1.0")]

In the AttributeUsage example, the parameter "ValidOn" is optional, while "Inherited" and "AllowMultiple" are named parameters.

Note: in order to set the value of a named parameter in the constructor of attribute, we must provide a set method for the corresponding property, otherwise it will cause a compile-time error:

'Version': Named attribute argument can't be a read only property

Now, what happens if we look up Help attribute and its properties in Class3? The result is the same compile-time error as mentioned above.

'Desciption': Named attribute argument can't be a read only property

Now let's modify the Help class to add a set method to the property "Description". The output now is:

Help.Description: This is do-nothing class

Help.Version: 2.0

What happened behind the screen? First the constructor with optional parameters is called, then the set method for each named parameter is called, and the value assigned to the named parameter in the constructor is overridden by the set method.

Parameter type

The parameter types of an attribute class are limited to the following types:

Attributes marker

Suppose we want to bind Help attribute to the element assembly. The question is, where do we put the Help attribute to get the compiler to determine that the attribute is bound to the entire assembly? Consider another situation where we want to bind attribute to the return type of a method. How can the compiler be sure that we are binding attribute to the return type of a method, rather than the entire method?

To solve such ambiguities, we use attribute identifiers, and with its help, we can declare exactly which language element we bind attribute to.

For example:

[assembly: Help ("this a do-nothing assembly")]

The assembly identifier before Help attribute tells the compiler exactly that the attribute is bound to the entire assembly. Possible identifiers are:

Query Attributes at run time

Now we know how to create attribtes and bind them to language elements. It's time to learn how users of classes can query this information at run time.

In order to query the attributes bound on a language element, we must use reflection. Reflection has the ability to discover type information at run time.

We can use the .NET Framework Reflection APIs to enumerate all the defined classes, types, and methods in assembly by iterating through the entire assembly metadata.

Remember the old Help attribute and AnyClass classes.

Using System; using System.Reflection; using System.Diagnostics; / / attaching Help attribute to entire assembly [assembly: Help ("This Assembly demonstrates custom attributes creation and their run-time query.")] / / our custom attribute class public class HelpAttribute: Attribute {public HelpAttribute (String Description_in) {/ TODO: Add constructor logic here this.description = Description_in / /} protected String description; public String Description {get {return this.deescription;} / / attaching Help attribute to our AnyClass [HelpString ("This is a do-nothing Class.")] Public class AnyClass {/ / attaching Help attribute to our AnyMethod [Help ("This is a do-nothing Method.")] Public void AnyMethod () {} / / attaching Help attribute to our AnyInt Field [Help ("This is any Integer.")] Public int AnyInt;} class QueryApp {public static void Main () {}}

We will add the attribute query code to our Main method in the next two sections.

Query the Attributes of an assembly

In the next code, we first get the current process name, then load the assembly with the LoadForm () method in the Assembly class, then use the GetCustomAttributes () method to get the custom attributes bound to the current assembly, and then use the foreach statement to iterate through all attributes and try to transform each attribute into Help attribute. (the object to be transformed has the advantage of using the as keyword, that is, when the transformation is illegal, we will not have to worry about throwing an exception Instead of using a null value (null) as a result, the next line is to check whether the transformation is valid and empty, followed by the "Description" attribute of Help attribute.

Class QueryApp {public static void Main () {HelpAttribute HelpAttr; / / Querying Assembly Attributes String assemblyName; Process p = Process.GetCurrentProcess (); assemblyName = p.ProcessName + ".exe"; Assembly a = Assembly.LoadFrom (assemblyName); foreach (Attribute attr in a.GetCustomAttributes (true)) {HelpAttr = attr as HelpAttribute If (null! = HelpAttr) {Console.WriteLine ("Description of {0}:\ n {1}", assemblyName,HelpAttr.Description);}

The program output is as follows:

Description of QueryAttribute.exe:

This Assembly demonstrates custom attributes creation and

Their run-time query.

Press any key to continue

Query the Attributes of classes, methods, and class members

The only thing we are not familiar with in the following code is the * line in the Main () method.

Type type = typeof (AnyClass)

It uses the typeof operator to get a type object associated with our AnyClass class. The rest of the query class attributes code is similar to the above example and should not be explained (I think so).

To query the attributes of methods and class members, first we get all the methods and members that exist in the class, and then we query all the attributes associated with them, in the same way we query the class attributes.

Class QueryApp {public static void Main () {Type type = typeof (AnyClass); HelpAttribute HelpAttr; / / Querying Class Attributes foreach (Attribute attr in type.GetCustomAttributes (true)) {HelpAttr = attr as HelpAttribute If (null! = HelpAttr) {Console.WriteLine ("Description of AnyClass:\ n {0}", HelpAttr.Description) }} / / Querying Class-Method Attributes foreach (MethodInfo method in type.GetMethods ()) {foreach (Attribute attr in method.GetCustomAttributes (true)) {HelpAttr = attr as HelpAttribute If (null! = HelpAttr) {Console.WriteLine ("Description of {0}:\ n {1}", method.Name, HelpAttr.Description) } / / Querying Class-Field (only public) Attributes foreach (FieldInfo field in type.GetFields ()) {foreach (Attribute attr in field.GetCustomAttributes (true)) {HelpAttr= attr as HelpAttribute If (null! = HelpAttr) {Console.WriteLine ("Description of {0}:\ n {1}", field.Name,HelpAttr.Description) }} above is all the content of the article "how to use Attributes in C#". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report