1. What is attribute
The simple point of the feature is to add some additional information to the target element that we can get in a reflection during the run. The target element refers to an assembly, module, class, parameter, attribute, and so on, and the additional information refers to the member in the attribute class. It can be seen that the attribute class is actually a data structure, we can put a variety of information into the class, and the attribute class is associated with the specified target element, in the target element each associated with an attribute to create an instance of an attribute class, of course, it does more than that. The following is a 3-segment code that uses attributes, 3 classes respectively. The first one is the MyAttribute attribute class, the second is the target class MyClass associated with the attribute class, and the 3rd class is the main program class. In the first class, I used the AttributeUsage system attribute class, and. NET also provided us with a number of fixed-attribute classes, such as Serializable, Conditional, DllImport, flags, and so on. The function of the parameters of the AttributeUsage Class I have comments in the code, can add this feature can not be added, but this feature class in my program must be added. The reason is that I added 4 instances of the MyAttribute attribute to the second class MyClass, and only one instance is allowed by default. So I'm going to specify AllowMultiple as true in AttributeUsage, and if I don't specify compile, I'll get an error.
In the parameters of the AttributeUsage attribute class, it is not an instance created entirely in the form of a pass value, which can also be directly assigned to parameters such as AllowMultiple and inherited. For the former is usually a parameter in the constructor, we must assign a value to the constructor otherwise it cannot be initialized, so this type of parameter is a fixed parameter. For the latter, it is an optional parameter, and the careful point is that it is a property in the attribute class, such as assigning a value to the Hobby property in the second class MyClass. Because there are optional parameters in the parameter, MyClass can correlate 4 instances of the feature at the same time. In the third class, I get a custom array of attributes through GetCustomAttribute, which is actually an example of myattribute, so that you can get the data members from the instance object. This is the basic use of attribute, because the constructor is called when used, so the custom attribute class must have a public constructor. Putting the EXE file of the program into reflector can clearly see that the attribute is a class, the use of attributes is actually called the constructor of the attribute.
//features can also be used on attributes[AttributeUsage (AttributeTargets.All,//the target element can be any elementallowmultiple=true,//multiple attributes can be added to an element, false when only one instance of this attribute is allowed on an elementInherited=true)]//attributes can be inherited by a quilt class, false when not inherited classMyattribute:attribute {//Field Public stringName="default name"; Public intAge =0; stringhobby="Default Hobby"; //Properties Public stringHobby {Get{returnHobby;} Set{hobby =value;} } //Construction Method Publicmyattribute () {} PublicMyAttribute (stringNameintAge ) { This. Name =name; This. Age =Age ; } //instance Method Public voidhaha () {Console.WriteLine ("haha"); } }
View Code
[ my ()] [My (Hobby="Football")] [My ("Small Square", -)] [My ("Small white", -, hobby="Basketball")] classMyClass { Public voidhaha () {Console.WriteLine ("I'm the MyClass class ."); } }
View Code
classProgram {Static voidMain (string[] args) { /** would have liked to see if the default is to take the first instance, the result execution times wrong: Find multiple instances of the same type//get a feature instance on MyClass MyAttribute myattribut E = (myattribute) attribute.getcustomattribute (typeof (MyClass), typeof (MyAttribute)); See if this instance is an if (Myattribute!=null) {Console.WriteLine (myattribute.name); Console.WriteLine (Myattribute.age); Console.WriteLine (Myattribute.hobby); Myattribute.haha (); } */ //get an array of attribute instances on MyClass, there are 4 instances of MyAttributeMyattribute[] Myattributes = (myattribute[]) attribute.getcustomattributes (typeof(MyClass),typeof(myattribute)); MyAttribute MyAttribute= myattributes[0]; if(MyAttribute! =NULL) {Console.WriteLine (myattribute.name); Console.WriteLine (Myattribute.age); Console.WriteLine (Myattribute.hobby); Myattribute.haha (); } console.readline (); } } /*execution Result: small white 30 basketball haha*/
View Code
The role of 2.Attribute
Because of the existence of the feature, we can get some information when the program is running, and then make a logical judgment based on the information. For example, you can use attributes to ensure that the model object's data is completely stripped of the empty string, as shown in the following code. The first paragraph of code refers to the attribute class MyAttribute, the second code refers to the MyClass class using the attribute, the third code refers to the MyClass class extension method trim, the fourth code refers to the main program class programs. A MyClass object was created in the main method, and some spaces were deliberately specified when assigning a value to the object. Suppose you now need to MyClass this class as a database entity class people, its instance holds the input data, this data may have the space. In general, I have to call the trim () method to remove the whitespace, but if MyClass has a lot of properties then it will be a hassle and need to write a lot of ToString (). Trim () method. Using the feature + extension method can be a lot easier, adding a myattribute attribute to attributes that require whitespace removal, and then invoking the trim extension method of the instance object. In the Trim method, all the properties of the object are traversed, all the attributes of each property are traversed, and the attributes that hit the MyAttribute attribute are found, followed by ToString (). The Trim () method calls and re-assigns a value to the property so that only one sentence of MyClass is written. Trim () enables the ability to remove spaces. If there are no attributes, although you can use extension methods to remove a space from a property, we cannot remove the specified attribute, and we can only remove all string spaces of type strings in one breath.
[AttributeUsage (attributetargets.property,inherited=false, allowmultiple=false)] Public classTrimattribute:attribute {//Fields and Properties ReadOnlyType MyType; PublicType MyType {Get{return This. MyType;} } //constructor Function Publictrimattribute (Type type) {MyType=type; } }
View Code
classMyClass {[Trimattribute (typeof(string))] Public stringName {Get;Set; } [Trimattribute (typeof(string))] Public stringHobby {Get;Set; } [Trimattribute (typeof(string))] Public stringAddress {Get;Set; } }
View Code
//The extension method must be a static class, static method. Public Static classtrimattributeextension { Public Static voidTrim ( This Objectobj) {Type T=obj. GetType (); //get all the properties of the MyClass instance object foreach(PropertyInfo propincht.getproperties ()) { //get all the attributes on a property foreach(varattrinchProp. GetCustomAttributes (typeof(Trimattribute),true) {Trimattribute Trimattribute=(Trimattribute) attr; //get the value of the Prop property of obj ObjectO=prop. GetValue (obj,NULL); //if O is not null and the MyType property of an attribute instance on this property is a string type if(o!=NULL&& (Trimattribute.mytype = =typeof(string))) { //once the property is assigned a value, which is already trim (), you can see GetPropertyValue (obj, prop. Name) is actually O. ObjectNewValue =getpropertyvalue (obj, prop. Name). ToString (). Trim (); Prop. SetValue (obj, newvalue,NULL); } } } } //get the value represented by the property itself Private Static ObjectGetPropertyValue (ObjectInstancestringPropertyName) { //first get the instance type object, and then call the InvokeMember method,//The first parameter of this method means that you need to call the property, method, field "First Name", the second argument is what you call PropertyName to do,//here is the Get property, the fourth is the instance to be manipulated. Finally, the parameters that need to be passed in are called, so the attribute is not required and I am set to null. returnInstance. GetType (). InvokeMember (PropertyName, BindingFlags.GetProperty,NULL, instance,NULL); }}
View Code
classProgram {Static voidMain (string[] args) {MyClass MyClass=NewMyClass (); MyClass. Name="Small Square"; MyClass. Hobby="Basketball"; MyClass. Address="Hubei"; MyClass. Trim (); /*execution here will see the value of the above three properties of the hollow lattice all have no MyClass. Name = "small square"; MyClass. Hobby = "basketball"; MyClass. Address = "Hubei"; */Console.ReadLine (); } }
View Code
3. Understanding attribute in general
attribute, the information described by the data class describing the information is actually metadata. When we build the solution in VS, an EXE file appears in the Debug folder, which is called the portable executable PE in Windows. PE consists of 3 parts: PE header, IL, meta data. The primary role of the PE head is to identify this file as a PE file and to describe the entry point for executing the program in memory. Il does not have to say much, but one thing to note is that the IL directive often has metadata tokens. Metadata contains metadata tables and heap data structures. There are many classes in a program that are recorded in a metadata table for a record type in PE, as well as a metadata table for members that record methods, fields, and metadata tables that can reference other tables and heaps. These tables can be understood as tables in a database, where a constraint and association are established between tables through the primary foreign key. But I don't know how these tables are created, whether all the data for a certain member of the program is put together, or some data such as a field that is classified as a class. There are 4 heap data structures for metadata, namely, string, Blob, user string, GUID. There is also a metadata token in IL that can be understood as a pointer to the metadata, which contains 4 bytes. The first byte describes the type that the pointer points to, such as pointing to a class table or to a method table. The latter 3-byte description points to the location in the target table, which is a bit like ZigBee programming. again, the role of metadata, all members defined in the program, as well as the externally introduced members will be described in the metadata, so that the JIT generation machine instruction is through the information in the metadata to complete the immediate compilation. The description of the assembly in the metadata stored in the program (name, version, other dependent assembly, etc.), the description of the type (class member, accessibility, inheritance implementation relationship, and so on), attributes. Here you can understand that the attribute is part of the metadata in the PE, specific to the physical structure I think there is a metadata attribute table, such as a type metadata table of a class has a pointer to its metadata attribute table, this attribute table records all the attributes associated with this class. In addition, because the attribute is part of the metadata, the attribute class will be instantiated at compile time, rather than the run-time dynamic instantiation.
C # Basics of attribute