C # properties (attributes) the Attribute

First clear a concept:

Metadata. .NET assembly metadata refers namespace, class, method, attribute information. This information can be read out via Reflection.

Let's look at an example:

#define BUG
//#define NOBUG
using System;
using System.Diagnostics;

namespace AttributeExample
{
    public static class AttributeTest
    {
        [Conditional("BUG")]
        public static void OutputDebug(string msg)
        {
            Console.WriteLine(msg + " : bug");
        }

        [Conditional("NOBUG")]
        public static void OutputMessage(string msg)
        {
            Console.WriteLine(msg + " : no bug");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            AttributeTest.OutputDebug("Function");
            AttributeTest.OutputMessage("Function");
            Console.Read();
        }
    }
}

operation result:

The #define BUG commented, # define NOBUG comments cancellation, re-run the results are as follows:

 

It can be understood that the above code [the Conditional ()] acts conditions. This is a feature.


Feature is the tag for transmitting behavior information declarative program various elements (classes, methods, structures, enumerations, etc.) at runtime. You can add declarative information to the program by using the feature. This information is added to the metadata. .NET Framework properties include Common Attributes and the Custom the Attributes . Common Attributes which comprises Global Attributes, Obsolete Attributes, Conditional Attributes , Caller Info Attributes.

Common Attributes

  • Global Attributes global characteristics, applied to the entire assembly. Uppermost end code is placed using. Global feature provides a set of program information, divided into three categories:
    • Assembly identity attributes procedures set identifier characteristics. name, version, and culture of these three characteristics for determining an identifier of an assembly. Properties can look at the project in the following AssemblyInfo.cs file.
    • Informational attributes characteristic information, some related to the company or product information, including AssemblyProductAttribute, AssemblyTrademarkAttribute and so on.
    • Assembly manifest attributes assembly manifest characteristics. Including title, description, default alias, and configuration.
  • Conditional Attributes 标记了一个条件方法,其执行依赖于指定的预处理标识符(#define),实例就是上面那个。条件特性可以同时使用多个。比如[Conditional("A"), Conditional("B")]。
  • Obsolete Attributes 标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。其语法表示为:[Obsolete(message)]、[Obsolete(message, iserror)]

其中,message是一个string,描述项目为什么过时以及该替代使用什么;iserror是一个bool,如果为true,编译器应该把项目的使用当做一个错误,默认值是false,此时编译器生成一个警告。比如下面的例子:

using System;
using System.Diagnostics;

namespace AttributeExample
{
    class Program
    {
        [Obsolete("Don't use OldMethod, use NewMethod instead", true)]
        static void OldMethod()
        {
            Console.WriteLine("It is the old method");
        }
        static void NewMethod()
        {
            Console.WriteLine("It is the new method");
        }

        static void Main(string[] args)
        {
            OldMethod();
            Console.Read();
        }
    }
}

这时程序无法编译,显示如下的错误:

  • Caller Info Attributes 通过使用该特性,可以获取调用某个方法的调用者的信息。比如代码的文件路径、代码的行等。比如下面所示的代码。
using System;
using System.Runtime.CompilerServices;

namespace AttributeExample
{
    class Program
    {
        public static void DoSomething()
        {
            TraceMessage("Something happened.");
        }

        public static void TraceMessage(string message,
            [CallerMemberName] string memberName = "",
            [CallerFilePath] string sourceFilePath = "",
            [CallerLineNumber] int sourceLineNumber = 0)
        {
            Console.WriteLine("message: " + message);
            Console.WriteLine("member name: " + memberName);
            Console.WriteLine("source file path: " + sourceFilePath);
            Console.WriteLine("source line number: " + sourceLineNumber);
        }

        static void Main(string[] args)
        {
            DoSomething();
            Console.Read();
        }
    }
}

运行结果如图所示:

Custom Attributes

 .NET框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任务目标元素相关。创建并使用自定义特性包含四个步骤:

1. 声明自定义特性

 一个新的自定义特性应派生自System.Attribute类,比如:

   // 声明名为FirstAttribute的自定义特性 
  [AttributeUsage(AttributeTargets.Class, Inherited =false)] class FirstAttribute : Attribute { }   
  // 声明名为SecondAttribute的自定义特性 [AttributeUsage(AttributeTargets.Class)]
class SecondAttribute : Attribute { }
  // 声明名为ThirdAttribute的自定义特性 [AttributeUsage(AttributeTargets.Class, AllowMultiple
=true)] class ThirdAttribute : Attribute { }

又比如:

   // 声明名为CustomAttribute的自定义特性 
  [AttributeUsage(AttributeTargets.Class| AttributeTargets.Constructor| AttributeTargets.Field| AttributeTargets.Method| AttributeTargets.Property, AllowMultiple =true)] public class CustomAttributes : System.Attribute{}

2.构建自定义特性

上面已经声明了一个名为CustomAttribute的自定义特性,现在构建这个特性。该特性将存储调试程序获得的信息,包括:bug的代码编号、辨认该bug的开发人员名字、最后一次审查该代码的日期以及一个存储了开发人员标记的字符串消息。

CustomAttribute类将带有三个用于存储前三个信息的私有属性和一个用于存储消息的公有属性。因此bug编号、开发人员名字和审查日期将是CustomAttribute类的必需的定位(positional)参数,消息将是一个可选的命名(named)参数。每个特性必须至少有一个构造函数。必需的定位参数应通过构造函数传递,如下面的代码所示:

    [AttributeUsage(AttributeTargets.Class|
        AttributeTargets.Constructor|
        AttributeTargets.Field|
        AttributeTargets.Method|
        AttributeTargets.Property,
        AllowMultiple =true)]
    public class CustomAttributes : System.Attribute
    {
        public int BugNo { get; }
        public string Developer { get; }
        public string LastReview { get; }
        public string Message { get; set; }

        public CustomAttributes(int BugNo, string Developer, string LastReview)
        {
            this.BugNo = BugNo;
            this.Developer = Developer;
            this.LastReview = LastReview;
        }
    }

3.在目标程序元素上应用自定义特性

通过把特性放置在紧接着它的目标之前,来应用该特性:

    [CustomAttributes(45,"Zara Ali","12/8/2012", Message ="Return type mismatch")]
    [CustomAttributes(49,"Nuha Ali","10/10/2012",Message ="Unused variable")]
    class Rectangle
    {
        protected double length;
        protected double width;
        public Rectangle(double length, double width)
        {
            this.length = length;
            this.width = width;
        }

        [CustomAttributes(55,"Zara Ali","19/10/2012", Message ="Return type mismatch")]
        public double GetArea()
        {
            return length * width;
        }

        [CustomAttributes(56,"Zara Ali", "19/10/2012")]
        public void Display()
        {
            Console.WriteLine("Length: {0}", length);
            Console.WriteLine("Width: {0}", width);
            Console.WriteLine("Area: {0}", GetArea());
        }
    }    

4.通过反射访问特性

别忘了使用using System.Reflection;

class ExecuteRectangle
    {
        static void Main(string[] args)
        {
            Rectangle r = new Rectangle(4.5, 7.5);
            r.Display();
            object[] attrs = r.GetType().GetCustomAttributes(false);
            // 遍历Rectangle类的特性
            foreach(Attribute attr in attrs)
            {
                CustomAttributes attribute = (CustomAttributes)attr;
                if(null != attribute)
                {
                    Console.WriteLine("Bug no: {0}", attribute.BugNo);
                    Console.WriteLine("Developor: {0}", attribute.Developer);
                    Console.WriteLine("Last Reviewed: {0}", attribute.LastReview);
                    Console.WriteLine("Remarks: {0}", attribute.Message);
                }
            }

            // 遍历方法特性
            object[] methods = r.GetType().GetMethods();
            foreach(MethodInfo method in methods)
            {
                foreach(object attribute in method.GetCustomAttributes(true))
                {
                    CustomAttributes attr = attribute as CustomAttributes;
                    if(null != attr)
                    {
                        Console.WriteLine("Bug no: {0}, for Method: {1}", attr.BugNo, method.Name);
                        Console.WriteLine("Developer: {0}", attr.Developer);
                        Console.WriteLine("Last Reviewed: {0}", attr.LastReview);
                        Console.WriteLine("Remarks: {0}", attr.Message);
                    }
                }
            }
            Console.Read();
        }
    }

运行结果如图所示:

 

参考文献:

1.https://www.runoob.com/csharp/csharp-attribute.html

2.https://www.runoob.com/csharp/csharp-reflection.html

3.https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/attributes/

4.https://blog.csdn.net/xiaouncle/article/details/70216951

 

Guess you like

Origin www.cnblogs.com/larissa-0464/p/11417337.html