C # Introduction to custom features

Source: Internet
Author: User

This article introduces the C # custom feature through examples. If you cannot define a feature and use it yourself, I don't think you can understand it very well.
AD:

C # examples of custom features
If you cannot define a feature and use it by yourself, I don't think you can understand it very well. Now let's build a feature by ourselves. Suppose we have a very common requirement: When we create or update a class file, we need to explain when and who created the class, in future updates, we also need to explain when the updated content will be updated. You can record or not record the updated content. What would you do in the past? Is it like this to add a comment to the class above the class:
// Update: Matthew,. Modify the ToString () method.
// Updated: Jimmy
// Create: Zhang Ziyang
Public class DemoClass {
// Class Body
}
This can indeed be recorded, but what if one day we want to save these records to the database for backup? Do you want to view the source files one by one, find out the comments, and insert them into the database one by one?
Through the definition of the above feature, we know that the feature can be used to add metadata to the type (data describing the data, including whether the data is modified, when it was created, and when it was created, the data can be a class, method, or attribute. The metadata can be used to describe the type. In this case, features should be used. In this example, the metadata should be: annotation type ("Update" or "CREATE"), modifier, date, and remarks (optional ). The target type of the feature is the DemoClass class.
Based on our understanding of the metadata appended to the DemoClass class, we first create a class RecordAttribute that encapsulates the metadata:
Public class RecordAttribute {
Private string recordType; // record type: update/create
Private string author; // author
Private DateTime date; // update/create date
Private string memo; // remarks

// Constructor. The constructor parameters are also called "location parameters" in features ".
Public RecordAttribute (string recordType, string author, string date ){
This. recordType = recordType;
This. author = author;
This. date = Convert. ToDateTime (date );
}

// For location parameters, only get accessors are provided.
Public string RecordType {get {return recordType ;}}
Public string Author {get {return author ;}}
Public DateTime Date {get {return date ;}}

// Construct an attribute, which is also called "name parameter" in a feature"
Public string Memo {
Get {return memo ;}
Set {memo = value ;}
}
}
 
NOTE: The date parameter of the constructor must be a constant, Type, or constant array. Therefore, the DateTime Type cannot be directly transferred.
This class not only looks like it, but is actually no different from a common class. Obviously, it cannot be changed to a feature because it is followed by an Attribute. So how can we call it a feature and apply it to a class? Before proceeding to the next step, let's take a look at how the built-in features of. Net are defined:
Namespace System {
[Serializable]
[AttributeUsage (6140, Inherited = false)]
[ComVisible (true)]
Public sealed class ObsoleteAttribute: Attribute {
 
Public ObsoleteAttribute ();
Public ObsoleteAttribute (string message );
Public ObsoleteAttribute (string message, bool error );
 
Public bool IsError {get ;}
Public string Message {get ;}
}
}
Format of adding features (location parameters and naming parameters)
First, we should find that it inherits from the Attribute class, which means that our RecordAttribute should also inherit from the Attribute class. (The difference between a feature class and a common class is that it inherits the Attribute class)
Secondly, we found that three features are used to describe this feature. These three features are: Serializable, AttributeUsage, and ComVisible. The Serializable feature has been described earlier. ComVisible is simply a definition defined by Microsoft to "control the accessibility of individual managed types, members, or all types of COM in a program set ). Here we should note that features are used to describe the metadata of data, and these three features are used to describe features, so they can be considered as "metadata" (metadata: meta-metadata ).
(From this we can see that the feature class itself can also be described by other features except itself, so the feature of this feature class is metadata .)
Because we need to use "meta data" to describe our defined feature RecordAttribute, so now we need to first understand "meta data ". Here we should remember that "meta-data" is also a feature. In most cases, we only need to master AttributeUsage, so now let's take a look at it. First, let's take a look at how AttributeUsage is loaded to the ObsoleteAttribute feature.
[AttributeUsage (6140, Inherited = false)]
Then let's take a look at the definition of AttributeUsage:
Namespace System {
Public sealed class AttributeUsageAttribute: Attribute {
Public AttributeUsageAttribute (AttributeTargets validOn );
 
Public bool AllowMultiple {get; set ;}
Public bool Inherited {get; set ;}
Public AttributeTargets ValidOn {get ;}
}
}
 
As you can see, it has a constructor, which contains a AttributeTargets type location Parameter (Positional Parameter) validOn, and two Named parameters (Named Parameter ). Note that the ValidOn attribute is not a named parameter because it does not contain the set accessors (location parameters ).
Here, you may wonder why parameters are divided in this way, which is related to the use of features. If AttributeUsageAttribute is a common class, we must use it like this:
// Instantiate an AttributeUsageAttribute class
AttributeUsageAttribute usage = new AttributeUsageAttribute (AttributeTargets. Class );
Usage. AllowMultiple = true; // you can specify the AllowMutiple attribute.
Usage. Inherited = false; // you can specify the Inherited attribute.
However, the feature is written as only one line of code and then closely related to the type (target type) applied by the feature. What should I do? Microsoft's software engineers came up with the following method: no matter the parameters or attributes of the constructor, they are all written into the parentheses of the constructor. For the constructor parameters, the parameters must follow the order and type of the constructor parameters. For properties, they are separated by commas (,) in the format of "property = value. The code above is reduced to the following:
[AttributeUsage (AttributeTargets. Class, AllowMutiple = true, Inherited = false)]
It can be seen that AttributeTargets. Class is a constructor parameter (location parameter), while AllowMutiple and Inherited are actually attributes (named parameters ). The name parameter is optional. In the future, our RecordAttribute will be used in the same way. (Why do they call parameters? I guess they look more like method parameters .)
Assume that our RecordAttribute has been OK, and its usage should be as follows:
C # code
[RecordAttribute ("CREATE", "Zhang Ziyang", "", Memo = "this class is for demonstration only")]
Public class DemoClass {
// ClassBody
}
RecordType, author, and date are the location parameters, while Memo is the naming parameter.
C # custom feature: AttributeTargets bit mark
We can see from the AttributeUsage attribute name that it is used to describe the usage of the feature. Specifically, it should first be the types or objects that the marked features can apply. From the code above, we can see that the AttributeUsage feature constructor accepts a AttributeTargets type parameter. Now let's take a look at AttributeTargets.
AttributeTargets is a single-digit tag that defines the types and objects that a feature can apply.
[Flags]
Public enum AttributeTargets {
Assembly = 1, // attributes can be applied to the Assembly.
Module = 2, // you can apply attributes to the Module.
Class = 4, // you can apply attributes to a Class.
Struct = 8, // you can apply properties to the structure, that is, the value type.
Enum = 16, // You can enumerate application attributes.
Constructor = 32, // you can apply attributes to the Constructor.
Method = 64, // attributes can be applied to the Method.
Property = 128, // you can apply an Attribute to a Property ).
Field = 256, // you can apply attributes to fields.
Event = 512, // attributes can be applied to the Event.
Interface = 1024, // you can apply attributes to interfaces.
Parameter = 2048, // you can apply attributes to parameters.
Delegate = 4096, // you can Delegate application attributes.
ReturnValue = 8192, // you can apply the attribute to the returned value.
GenericParameter = 16384, // you can apply attributes to generic parameters.
All = 32767, // you can apply attributes to any application element.
}
It is not difficult to understand why the above examples use:
[AttributeUsage (AttributeTargets. Class, AllowMutiple = true, Inherited = false)]
The AttributeUsage loaded on the ObsoleteAttribute feature is as follows:
[AttributeUsage (6140, Inherited = false)]
Because AttributeUsage is a single-digit tag, it can be combined by bit or "|. So when we write this:
[AttributeUsage (AttributeTargets. Class | AttributeTargets. Interface)
This means that features can be applied to both classes and interfaces.
NOTE: There are two special cases: observing the AttributeUsage definition above, it means that the feature can also be loaded to Assembly and Module, and these two are our compilation results, this type does not exist in the program. How should we load it? You can use the syntax [assembly: SomeAttribute (parameter list)]. In addition, this statement must be prior to the start of a Program Statement.
C # custom features: Inherited and AllowMutiple attributes
The AllowMutiple attribute is used to set whether the feature can be added to a type repeatedly (the default value is false), as shown in the following figure:
[RecordAttribute ("Update", "Jimmy", "")]
[RecordAttribute ("CREATE", "Zhang Ziyang", "", Memo = "this class is for demonstration only")]
Public class DemoClass {
// ClassBody
}
Therefore, we must set AllowMutiple to True.
Inherited is more complicated. If a class inherits from our DemoClass, when we add recordattriclass to DemoClass, The DemoClass subclass also obtains this feature. When a feature is applied to a method, if the method is overwritten by a subclass Inherited from this class, then Inherited is used to show whether the subclass method inherits this feature.
In our example, set Inherited to false.
C # custom features: Implement RecordAttribute
Now it is very easy to implement RecordAttribute. You do not need to make any changes to the class subject. We only need to make it inherit from the Attribute base class, you can also mark it with the AttributeUsage feature (assuming we want to apply this feature to classes and methods ):
[AttributeUsage (AttributeTargets. Class | AttributeTargets. Method, AllowMultiple = true, Inherited = false)]
Public class RecordAttribute: Attribute {
// Omitted
}
C # custom features: Use RecordAttribute
We have created our own custom features, and now it is time to use them.
C # code
[Record ("Update", "Matthew", "2008-1-20", Memo = "Modify ToString () method")]
[Record ("Update", "Jimmy", "")]
[Record ("CREATE", "Zhang Ziyang", "")]
Public class DemoClass {
Public override string ToString (){
Return "This is a demo class ";
}
}

Class Program {
Static void Main (string [] args ){
DemoClass demo = new DemoClass ();
Console. WriteLine (demo. ToString ());
}
}
This program simply outputs a "This is a demo class" on the screen ". Our properties also seem to have no impact on the program as if we used "//" for annotation. In fact, the data we added has been added to the Assembly as metadata. You can see through il dasm:

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.