What isAttribute(Feature )? AndPropertyWhat is the difference between attributes?
Let's take a look at the description of the feature in MSDN:
Attribute Class associates predefined system information or user-defined custom information with the target element. The target element can be an assembly, class, constructor, Delegate, enumeration, event, field, interface, method, executable file module, parameter, attribute, return value, structure, or other features.. Features are sent to metadata when you compile code, and can be used by runtime reflection Service for Public language runtime and any custom tools or applications. You can use Attribute to add some additional information to some target elements (such as classes, fields, and interfaces ), when the program is compiled, the additional information is serialized into the Assembly metadata. When you run the program, the additional information can be read from the Assembly metadata through reflection technology, determine the behavior of your program based on the additional information.
What is the difference between Attribute and Property? In fact, this problem is for developers of Chinese backgrounds, because many Chinese translations translate Attribute and Property into attributes. In order to distinguish between them, we translate Attribute into features, attribute and Property are basically irrelevant because they are. in NET, the Property is the Attribute defined in the class that we are no longer familiar with. It belongs to the scope of object-oriented theory, and Attribute is the syntactic aspect of programming language, the definition is described in the preceding section.
You used. NETDefinedAttribute?
Many custom attributes are provided in the. NET base class library for developers to use. These Custom Attributes facilitate developers to express their intentions in code. For example, the following three Attribute classes are all feature classes that the C # compiler can understand:
Obsolete: This attribute is used to mark program entities (such as classes or methods) that are no longer used. Each time an object marked as Obsolete is used, a method for setting this attribute is set to generate warnings or errors.
Conditional: This feature can indicate whether a method should be called in an environment setting.
Serializable: indicates that a class can be serialized.
The following uses the Obsolete feature as an example to describe how Attribute applies its target element.
Namespace AttributeDemo
{
Class Program
{
Static void Main (string [] args)
{
MyClass myclass = new MyClass ();
Myclass. OldMethod ();
Console. ReadKey ();
}
}
Public class MyClass
{
[Obsolete ("this is an old method. Please call the new method NewMethod")]
Public void OldMethod ()
{
Console. WriteLine ("this is the old method ");
}
Public void NewMethod ()
{
Console. WriteLine ("this is a new method ");
}
}
}
When debugging this program, a warning is issued, as shown in:
For custom features such as Obsolete, the compiler can handle the issue accordingly. For example, a warning will be issued when a method marked with the Obsolete feature is used, but if we customize the Attribute, what will the compiler do. Next we will define an Attribute.
I will also defineAttribute
To comply with the "public language specification" (CLS), custom Attribute must be derived directly or indirectly from the public abstract class System. Attribute. Therefore, we mentioned earlier that Obsolete, Conditional, and Serializable are derived from Attribute. Here, we need to describe the custom Attribute naming rules. The rule is "feature name + Attribute", that is, we must use Attribute as the suffix for customization, the three features we mentioned above do not have the Attribute suffix. They are all defined with the Attribute suffix. For example, the Obsolete is the ObsoleteAttribute, when we apply a feature to a target element, we can remove the Attribute suffix, because the compiler will first find the feature without the Attribute suffix, if not, the feature name with the Attribute suffix is searched.
The System. Attribute constructor is modified by protected, indicating that it cannot be instantiated by itself and can only be called by its derived class. It has three important static methods:
Method Name |
Description |
GetCustomAttributes |
There are multiple reloads. The returned array acts on the Target Attribute class instance, that is, the returned type is Attribute []. |
GetCustomAttribute |
If there are multiple overloading, an instance of the Attribute class acting on the target is returned. If the target does not apply any Attribute, null is returned. If the target applies multiple instances of the specified Attribute, throw a System. reflection. ambiguousMatchException. |
IsDefined |
If at least one specified Attribute derived class instance acts on the target, true is returned; otherwise, false is returned. This method is highly efficient because it does not build an Attribute instance. The previous two methods return an Attribute instance, that is, the instance needs to be constructed by obtaining information from the metadata, which consumes a lot of performance. |
When you check whether an Attribute is applied to a target element, System is called. attribute. the IsDefined method has higher performance than GetCustomAttributes and GetCustomAttribute. If you need to return the Attribute instance, call the GetCustomAttributes or GetCustomAttribute method. All three methods scan the metadata of the managed module (because the Attribute is saved on the metadata of the managed module during compilation) and execute string comparison to define the specified Attribute class. This operation consumes a lot of time performance. If you need to call these methods repeatedly, You Can cache the call results of these methods, that is, save the instance in a global variable, you do not need to scan and construct instances every time.
Except System. attribute Class provides the preceding three static methods to check whether Attribute is applied to the target element. some classes defined in the Reflection namespace also allow you to check the metadata content of a Module. These classes include Assembly, Module, ParameterInfo, MemberInfo, Type, MethodInfo, ConstrucorInfo, FieldInfo, EventInfo, propertyInfo and so on. They all provide the GetCustomAttributes and IsDefined methods. The types returned by the GetCustomAttributes class are Object [], while the GetCustomAttributes method of the System. Attribute Class returns Attribute [].
The following uses the GetCustomAttributes method provided by System. Attribute and System. Reflection. Type to obtain the Attribute instance. The sample code is provided to give you a more intuitive understanding.
Define an Attribute
Public class MyMsgAttribute: Attribute
{
Public string Msg {get; set ;}
Public MyMsgAttribute (string msg)
{
Msg = msg;
}
}
Define a class so that the custom MyMsgAttribute class can be applied to this class as follows:
[MyMsgAttribute ("My custom Attribute")]
Public class MyClass
{
}
Use the GetCustomAttributes method provided by System. Reflection. Type to obtain the instance of the MyMsgAttribute class. The Code is as follows:
Var attributes = typeof (MyClass). GetCustomAttributes (typeof (mymsgattrites), true );
MyMsgAttribute myAttribute = attributes [0] as MyMsgAttribute;
If (myAttribute! = Null)
{
Console. WriteLine (myAttribute. Msg );
}
Use the GetCustomAttributes method provided by System. Attribute to obtain the instance of the MyMsgAttribute class. The Code is as follows:
Var attributes2 = Attribute. GetCustomAttributes (typeof (MyClass ));
MyMsgAttribute myAttribute2 = (MyMsgAttribute) attributes2 [0];
Console. WriteLine (myAttribute2.Msg );
The output result of the above two codes is that Msg is the property value -- "My custom Attribute ".
After analyzing the above two pieces of code, we already know how to customize an Attribute class and apply this Attribute to a class, at the same time, we learned how to construct the Attribute instance from metadata during runtime. We can get the Attribute object and execute some logic branch code based on the object information, the above is just a simple output of the Attribute object Msg Attribute value. It can be seen that custom Attribute is very useful because it can decide to execute different logic branch code at runtime. For example, we can use IsDefined to check whether SerializableAttribute is applied to a class to determine whether the class can be used for serialization.
When we use Attribute to apply a target element, we will find that some attributes can be applied to classes or attributes, such as SerializableAttribute, however, some attributes can only be applied to the target element of a method, such as ConditionalAttribute. Why are different attributes different from each other? We can view the definitions of these two attributes and find that they apply an Attribute class, which is AttributeUsage. Because Attribute itself is a class, it allows other Attribute classes to be applied. The AttributeUsage aims to limit the type of elements applied by your Attribute. For example, it limits whether your Attribute can be applied to a class, method, or Attribute.
The AttributeUsage constructor has a parameter, which is an enumeration type of AttributeTargets.
The names of the enumerated members of AttributeTargets are described as follows:
All can apply features to any application element.
Assembly can be applied to Assembly features.
Class can be applied to Class features.
Constructor can apply features to Constructor.
Delegate can be used to Delegate application features.
Enum can be used to enumerate application features.
Event can apply features to events.
Field can be applied to the Field.
GenericParameter can apply features to generic parameters.
Interface can be applied to Interface features.
Method can apply features to the Method.
Module can apply features to modules. Note that the Module refers to a portable executable file (. dll or. EXE), rather than a standard Visual Basic Module.
If your custom Attribute does not apply AttributeUsage explicitly, the compiler automatically adds a default AttributeUsage to you, and the default constructor parameter is AttributeTargets. all, that is, your custom Attribute can apply the following element type: Assembly | Module | Class | Struct | Enum | Constructor | Method | Property | Field | Event | Interface | Parameter | Delegate,
ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface.
If your custom Attribute only applies to classes and methods, the instance code is as follows:
[AttributeUsage (AttributeTargets. Class | AttributeTargets. Method)]
Public class MyMsgAttribute: Attribute
{
Public string Msg {get; set ;}
Public MyMsgAttribute (string msg)
{
Msg = msg;
}
}
The mymsgattrigatdefined in this way can only be applied to classes and methods, and an error will be reported during compilation when it is applied to target elements of other types.
The AttributeUsage class provides two common attributes: AllowMultiple and Inherited. AllowMultiple is used to allow multiple Attribute instances to be applied to the same target element. When AttributeUsage is applied to a custom Attribute, the value of AllowMultiple can be set to True, in this way, the custom Attribute allows multiple instances to be applied to a single target element. If the AllowMultiple display is not set to True, the custom Attribute can be applied only once to a selected target element. The Inherited Attribute specifies whether the custom Attribute is applied to both the derived class and the override method when applied to the base class. The following code demonstrates the concepts of AllowMultiple and Inherited:
[AttributeUsage (AttributeTargets. Class | AttributeTargets. Method, AllowMultiple = true, Inherited = true)]
Public class MyMsgAttribute: Attribute
{
Public string Msg {get; set ;}
Public MyMsgAttribute (string msg)
{
Msg = msg;
}
}
[MyMsgAttribute ("My custom Attribute")]
[MyMsgAttribute ("your custom Attribute")]
Public class MyClass
{
Public string Name {get; set ;}
Public string GetName ()
{
Return Name;
}
}
Public class YourClass: MyClass
{}
Static void Main (string [] args)
{
Var attributes = typeof (MyClass). GetCustomAttributes (typeof (mymsgattrites), true );
Foreach (var attribute in attributes)
{
MyMsgAttribute myAttribute = attribute as MyMsgAttribute;
If (myAttribute! = Null)
{
Console. WriteLine (myAttribute. Msg );
}
}
Attributes = typeof (YourClass). GetCustomAttributes (typeof (mymsgattrites), true );
Foreach (var attribute in attributes)
{
MyMsgAttribute myAttribute = attribute as MyMsgAttribute;
If (myAttribute! = Null)
{
Console. WriteLine (myAttribute. Msg );
}
}
Console. ReadKey ();
}
The output result is:
Summary
Based on the analysis in the above article, we will summarize the definition and use of custom attributes:
1. The custom Attribute must be derived from System. Attribute.
2. Apply AttributeUsageAttribute to the custom Attribute to apply the target element and whether the target element can apply multiple instances of the same Attribute, whether the Attribute applied by the target element can be used to control the override methods of the derived and derived classes.
3. The custom Attribute is stored on the module metadata during compilation, and the Attribute instance is constructed by reading information from the metadata at runtime.
4. To obtain or determine the information of an Attribute applied to a target element, you can use the three lens Methods provided by System. Attribute. IsDefined,
System. attribute. getCustomAttributes and System. attribute. getCustomAttribute, you can also use System. reflection namespace defines some classes to check the metadata content of a Module. These classes include Assembly, Module, ParameterInfo, MemberInfo, Type, MethodInfo, ConstrucorInfo, FieldInfo, EventInfo, PropertyInfo, etc, they all provide the GetCustomAttributes and IsDefined methods.