This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

C# features 🔥 (Attribute)

What is the feature 🙏

Attributes are declarative tags that are used at run time to pass information about the behavior of various elements in a program, such as classes, methods, structures, enumerations, components, and so on. You can add declarative information to a program by using features. A declarative tag is described by placing square brackets ([]) before the element to which it applies. Attributes are used to add metadata such as compiler directives and other information such as annotations, descriptions, methods, classes, and so on. The.NET framework provides two types of features: predefined features and custom features.

Feature function 🎅

Used to associate metadata or declarative information with code (procedural sets, types, methods, attributes, etc.)

Feature Description 🎄

  • Feature to add metadata to a program
  • One or more features can be applied to entire assemblies, modules, or smaller program elements (such as classes and attributes) – multiple features can be added to a program element
  • Properties can take parameters in the same way as square methods and properties – properties can take parameters
  • Programs can use reflection to examine their own metadata or metadata within other programs
  • Features (metadata) are defined after compilation

🎁(Meta Data)

Description: Metadata is binary information used to describe a program stored in a common language running line library portable executable (PE) file or stored in memory. When compiling your code into a PE file, poop inserts metadata into one part of the file and converts the code into Microsoft Intermediate Language (MSIL) and inserts it into another part of the file. Each type and member defined and referenced in a module or assembly is described in the metadata. As the code executes, the runtime loads the metadata into memory and references it to discover information about the code’s classes, members, inheritance, and so on.

Predefined features 💬

AttributeUsage 🎉

This important still difficult! Description: The predefined attribute AttributeUsage is used to indicate which types of program elements a custom attribute can be applied to. This information is instantiated by the first parameter:

[AttributeUsage(validon,// Specifies the language element in which the attribute can be placed. It is a combination of the value of the enumerator AttributeTargets. The default value is AttributeTargets AllowMultiple= AllowMultiple, // If true, this feature can be used multiple times with the same element. The default value is false. The property can be inherited by a derived class. The default is false(not inherited).]
Copy the code

1.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[AttributeUsage(AttributeTargets.Class,AllowMultiple =true,Inherited =true)]
public class AuthorAttribute : Attribute
{
    public string author;
    public string lastDate;// The date of last modification
    public string LastDate
    {
        get
        {
            return lastDate;
        }
        set
        {
            lastDate = value; }}// The constructor for the current property
    public AuthorAttribute(string author)
    {
        this.author = author; }} [AttributeUsage(AttributeTargets.Method,AllowMultiple =true)]
public class MyConditionAttribute : Attribute
{
    public MyConditionAttribute(){}} [Author("Albert",lastDate = "1010.6.13"),Author("Tom",lastDate ="1010.10.13")]
public class UserAttributeDemo : MonoBehaviour
{
    public static  string log="abc";

    [MyCondition]
    public static void ShowLog(){ Debug.Log(log); }}2.using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Reflection;

[AddComponentMenu("My/UsesAttributeObserver")]
[RequireComponent(typeof(Rigidbody),typeof(BoxCollider))]// Component dependencies

public class UsesAttributeObserver : MonoBehaviour{[Header("Log delay time")]
    [Range (0100)]
    public float  logelayTime=100;

    [SerializeField]// Let private fields also be displayed on the monitor panel
    private string name;

    [ColorUsage(false)]
    public Color col;

    private void Start()
    {
        InvokeMethodByAttribute(typeof(MyConditionAttribute),"ShowLog".true.true);
    }

    /// <summary>
    ///Execute a method based on a feature
    /// </summary>
    /// <param name="methodClasstype">The type of the class in which the method resides</param>
    /// <param name="methodName">The method name</param>
    /// <param name="isStatic">Whether the static</param>
    /// <param name="isPublic">Whether the public</param>
    /// <param name="methodObj">Object where the member method resides</param>
    /// 
    private void InvokeMethodByAttribute(Type methodClasstype, string methodName,bool isStatic,bool isPublic,object methodObj=null)
    {

        BindingFlags staticFlags = isStatic ? BindingFlags.Static : BindingFlags.Instance;
        BindingFlags publicFlags = isPublic ? BindingFlags.Public  : BindingFlags.NonPublic;
        // Get the method
        MethodInfo info= methodClasstype.GetMethod(methodName, staticFlags | publicFlags);
        // Get the properties of the MyConditionAttribute type
        object[] atts= info.GetCustomAttributes(typeof(MyConditionAttribute), false);

        if (atts.Length>0)
        {
            //info.Invoke();
        }

        Debug.Log("");
    }


    void PrintAttributeMsg()
    {
        // Get the type
        Type type = typeof(UserAttributeDemo);
        // Get a non-inheritable property object of this type
        object[] atts= type.GetCustomAttributes(false);
        for (int i = 0; i < atts.Length; i++)
        {
            / / determine
           if(atts[i]is AuthorAttribute)
            {
                // Convert the feature to that type
                AuthorAttribute authorObj = atts[i] asAuthorAttribute; Debug.Log(authorObj.author); Debug.Log(authorObj.lastDate); }}}}Copy the code

Conditional 🎉

Conditional(“ZAY”) : Conditional(“ZAY”) : Conditional(“ZAY”) : Conditional(“ZAY”) : Conditional(“ZAY”) : Conditional(“ZAY”)

Description: This predefined feature identifies a conditional method whose execution depends on its top preprocessor identifier. It causes conditional compilation for method calls, depending on the specified value, such as Debug or Trace.

[Conditional("ABC")]

1.using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;

public class ConditionalDemo{[Conditional("ZAY")]
    public static void ShowMe()
    {
        Debug.Log("Show Me!"); }}public class HasConditionDemo : MonoBehaviour
{
    void Start(){}}2.
#define ZAY
using UnityEngine;
public class UseConditionalDemo : MonoBehaviour
{
    void Start(){ ConditionalDemo.ShowMe(); }}Copy the code

Obsolote 🎉

You can either mark the method as obsolete or set the method to directly unavailable description: This predefined feature marks program entities that should not be used. It lets you tell the compiler to discard a particular target element. For example, when a new method is used in a class, but you still want to keep the old method in the class, you can mark it obsolete by showing a message that the new method should be used, not the old one.

Example:

[Obsolete]
[Obsolete("The current method is outdated, please use a new method.")]
[Obsolete("Out of date",false)]

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class DemoFrame
{
    //[Obsolete]
    //[Obsolete(" current method is Obsolete, please replace him with NewDemoShowMe() ")]
    [Obsolete("The current method is outdated, please replace it with NewDemoShowMe().",false)]
    public static void OldDemoShowMe()
     {
        Debug.Log("OldDemoShoeMe");
      }
    public static void NewDemoShowMe()
    {
      Debug.Log("NewDemoShowMe"); }}public class UseObsoleteDemo : MonoBehaviour
{
    
    void Start(){ DemoFrame.NewDemoShowMe(); }}Copy the code

Custom features 🎈

The.NET framework allows you to create custom features that store declarative information that can be retrieved at run time. This information can be relevant to any target element, depending on design criteria and application needs. Creating and using custom features involves four steps:

  • Declare custom features
  • Build custom features
  • Apply custom features to target program elements
  • Access features by reflection

The final step involves writing a simple program to read metadata to find symbols. Metadata is data and information that describes other data. The program should use reflection to access features at run time

Example: I did this test in Unity, and the features are more useful

// Add to the menu
[AddComponentMenu("My/UsesAttributeObserver")]
// Component dependencies
[RequireComponent(typeof(Rigidbody),typeof(BoxCollider))]

[SerializeField]// Let private fields also be displayed on the monitor panel
private string name;
Copy the code

The following is an introduction diagram of custom featuresAttributes often work with reflections, too. I’ll look briefly at the definition and usage of Reflection next time

The following is a description of the use of the feature in MSDN:

  • In Web services, the WebMethod feature is used to mark a method to indicate that the method should be callable over the SOAP protocol. For more information, see WebMethodAttribute.

  • Describes how to marshal method parameters when interacting with native code. See MarshalAsAttribute for more information.

  • COM attributes that describe classes, methods, and interfaces.

  • Invoke unmanaged code using the DllImportAttribute class.

  • Describe your assembly in terms of title, version, description, or branding.

  • Describes which members of the serialized class to persist.

  • Describes how to map class members and XML nodes for XML serialization.

  • Describe the security requirements for the method.

  • Specifies the features used to enforce security.

  • Optimizations are controlled by a real-time (JIT) compiler for easy debugging of code.

  • Method to get information about the caller.