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

Example Analysis of C# Custom feature

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

This article is to share with you the content of a sample analysis of C# custom features. The editor thinks it is very practical, so share it with you as a reference and follow the editor to have a look.

Sample introduction of C# Custom Features

If you can't define a feature and use it, I don't think you can understand the feature very well, so let's build one ourselves now. Suppose we have such a common requirement: when we create or update a class file, we need to specify when and by whom the class was created, and when it was updated in the future. You can record or not record the updated content. What would you have done in the past? Do you want to add comments to the class like this:

/ / Update: Matthew, 2008-2-10, modify ToString () method / / Update: Jimmy, 2008-1-18 / / public class DemoClass {/ / Class Body}

It is true that it can be recorded, but what if one day we want to save these records to the database for backup? Do you want to look at the source files one by one, find these comments, and insert them into the database one by one?

From the definition of the above properties, we know that properties can be used to add metadata to types (data that describes whether the data has been modified, when it was created, and who created it, which can be a class, method, property). These metadata can be used to describe types. Then here, the feature should come in handy. So in this case, the metadata should be: comment type ("update" or "create"), modifier, date, comment information (optional). The target type of the feature is the DemoClass class.

According to the understanding of the metadata attached to the DemoClass class, let's 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 / creation date private string memo; / / remarks / / constructor, whose parameters are also called "position parameters" in properties. Public RecordAttribute (string recordType, string author, string date) {this.recordType = recordType; this.author = author; this.date = Convert.ToDateTime (date);} / / for location parameters, usually only the get accessor public string RecordType {get {return recordType;}} public string Author {get {return author }} public DateTime Date {get {return date;}} / / build an attribute, which is also called "named parameter" public string Memo {get {return memo;} set {memo = value;} in the property.

NOTE: note that the constructor argument date must be a constant, a Type type, or an array of constants, so you cannot pass the DateTime type directly.

This class not only looks, but is actually no different from an ordinary class, and obviously it can't be transformed into a feature just because the name is followed by an Attribute. So how do you call it a feature and apply it to a class? Before moving on, let's take a look at how the .net built-in feature Obsolete is 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;}}

Add the format of the property (position parameter and named parameter)

First of all, 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 normal class is that it inherits the Attribute class.)

Secondly, we find that in the definition of this feature, three more features are used to describe it. These three features are: Serializable, AttributeUsage, and ComVisible. As we mentioned earlier about the Serializable feature, ComVisible is simply "controlling the accessibility of individual managed types, members, or all types in an assembly to COM" (as defined by Microsoft). It should be noted here that features themselves are metadata used to describe data, and these three features are used to describe characteristics, so they can be considered "metadata of metadata" (metadata: meta-metadata).

(we can see here that the property class itself can also be described by features other than itself, so the property of this property class is metadata. )

Because we need to use "metadata" to describe the feature RecordAttribute that we define, we need to look at "metadata" first. It should be remembered here that "metadata" is also a feature, and in most cases, we just need to master AttributeUsage, so let's take a look at it now. Let's first look at how the above AttributeUsage is loaded into the ObsoleteAttribute feature.

[AttributeUsage (6140, Inherited = false)]

Then let's 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 that contains a positional parameter of type AttributeTargets (Positional Parameter) validOn, and two named arguments (Named Parameter). Note that the ValidOn property is not a named parameter because it does not contain a set accessor (which is a positional parameter).

Here you must wonder why the parameters are divided in this way, which is related to the use of features. If AttributeUsageAttribute is a normal class, we must use it like this:

/ / instantiate an AttributeUsageAttribute class

AttributeUsageAttribute usage=new AttributeUsageAttribute (AttributeTargets.Class)

Usage.AllowMultiple = true; / / set the AllowMutiple property

Usage.Inherited = false;// sets the Inherited property

However, what if the feature is written as a single line of code and then follows the type to which it applies (the target type)? Microsoft software engineers have come up with this way: whether the parameters or attributes of the constructor are written in parentheses of the constructor, the parameters of the constructor must be in accordance with the order and type of the parameters of the constructor; for attributes, the format "attribute = value" is used, and they are separated by commas. So the above code is reduced to this:

[AttributeUsage (AttributeTargets.Class, AllowMutiple=true, Inherited=false)]

As you can see, AttributeTargets.Class is a constructor parameter (positional parameter), while AllowMutiple and Inherited are actually attributes (named parameters). Named parameters are optional. In the future, we will use RecordAttribute in the same way. (why do you call them parameters? I guess it's because they are used in a way that looks more like the parameters of a method.)

Assuming that our RecordAttribute is now OK, it should be used like this:

C # code

[RecordAttribute ("create", "Zhang Ziyang", "2008-1-15", Memo= "this class is for demonstration only")] public class DemoClass {/ / ClassBody}

Where recordType, author and date are positional parameters, and Memo is named parameters.

C# Custom property: AttributeTargets bit tag

The name of the AttributeUsage feature shows how it is used to describe the feature. Specifically, the first thing should be the types or objects to which the marked properties can be applied. From the above code, we see that the constructor of the AttributeUsage feature accepts a parameter of type AttributeTargets, so let's take a look at AttributeTargets now.

An AttributeTargets is a bit tag that defines the types and objects to which a property can be applied.

[Flags]

Public enum AttributeTargets {

Assembly = 1, / / you can apply properties to the assembly.

Module = 2, / / you can apply attributes to the module.

Class = 4, / / you can apply attributes to the class.

Struct = 8, / / you can apply attributes, that is, value types, to the structure.

Enum = 16, / / you can apply properties to enumerations.

Constructor = 32, / / you can apply attributes to the constructor.

Method = 64, / / you can apply properties to the method.

Property = 128A Attribute can be applied to an attribute (Property).

Field = 256, / / you can apply properties to the field.

Event = 512, / / you can apply attributes to events.

Interface = 1024, / / attributes can be applied to the interface.

Parameter = 2048, / / you can apply attributes to the parameters.

Delegate = 4096, / / attributes can be applied to delegates.

ReturnValue = 8192, / / you can apply attributes to the return value.

GenericParameter = 16384, / / attributes can be applied to generic parameters.

All = 32767, / / you can apply attributes to any application element.

}

It should not be difficult to understand why my example above is:

[AttributeUsage (AttributeTargets.Class, AllowMutiple=true, Inherited=false)]

The AttributeUsage loaded on the ObsoleteAttribute feature looks like this:

[AttributeUsage (6140, Inherited = false)]

Because AttributeUsage is a bit tag, it can be combined using bitwise or "|". So, when we write like this:

[AttributeUsage (AttributeTargets.Class | AttributeTargets.Interface)

It means that features can be applied to both classes and interfaces.

NOTE: there are two special cases: look at the definition of AttributeUsage above and show that the features can also be loaded into the assembly Assembly and the module Module, and these two belong to our compilation results, which do not exist in the program. How can we load them? You can use this syntax: [assembly:SomeAttribute (parameter list)], and this statement must be before the start of the program statement.

C# custom features: Inherited and AllowMutiple properties

The AllowMutiple property is used to set whether the property can be repeatedly added to a type (default is false), like this:

[RecordAttribute ("update", "Jimmy", "2008-1-20")]

[RecordAttribute ("create", "Zhang Ziyang", "2008-1-15", Memo= "this class is for demonstration only")]

Public class DemoClass {

/ / ClassBody

}

So, we have to show that AllowMutiple is set to True.

Inherited is a little more complicated, and if there is a class that inherits from our DemoClass, then when we add RecordAttribute to DemoClass, the subclasses of DemoClass will also get this feature. When an attribute is applied to a method, if a subclass inheriting from that class overrides the method, then Inherited is used to indicate whether the subclass method inherits the property or not.

In our example, set Inherited to false.

C# Custom feature: implementing RecordAttribute

It should be very easy to implement RecordAttribute now. You don't need to make any changes to the body of the class, we just need to let it inherit from the Attribute base class and mark it with the AttributeUsage attribute (assuming we want to be able to apply this feature to classes and methods):

[AttributeUsage (AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=true, Inherited=false)]

Public class RecordAttribute:Attribute {

/ / slightly

}

C# Custom feature: using RecordAttribute

We've created our own custom feature, and now it's time to use it.

C # code

[Record ("update", "Matthew", "2008-1-20", Memo = "modify ToString () method")] [Record ("update", "Jimmy", "2008-1-18")] [Record ("create", "Zhang Ziyang", "2008-1-15")] 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 have no effect on the program as if they were annotated with "/ /". In fact, the data we added has been added to the assembly as metadata. You can see through IL DASM:

Thank you for reading! This is the end of this article on "sample Analysis of C# Custom Features". I hope the above content can be of some help to you, so that you can learn more knowledge. If you think the article is good, you can share it out for more people to see!

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