zoukankan      html  css  js  c++  java
  • C#反射和特性2 特性

    特性(attribute)是一种允许我们想程序的程序集增加元数据的语言结构。它是用于保存程序结构信息的某种特殊类型的类。

    将应用了特性的程序结构叫做目标(target)。

    设计用来获取和使用元数据的程序叫做特性的消费者(consumer)。

    .Net预定了很多特性,我们也可以声明自定义特性。

    开发人员将特性应用于程序,编译器获取源代码并从特性中产生元数据,然后把元数据放到程序集中,消费者程序可以获取特性的元数据以及程序中其他组件的元数据。

    特性通常以Attribute作为后缀,当为目标应用特性时,可以不使用后缀。

    几个官方特性:

    1、Obsolete,用于告知程序已经过期(提示警告或错误)

    2、Conditional,允许包括或排斥特定方法的所有调用。为方法声明应用Conditional特性并把编译符作为参数来使用

        class Program
        {
            [Obsolete("This method is obsolute")]
            static void PrintOut(string str)
            {
                Console.WriteLine(str);
            }
            [Conditional("DoTrace")]
            static void TraceMessage(string str)
            {
                Console.WriteLine(str);
            }
            static void Main(string[] args)
            {
                TraceMessage("Start of Main");
                PrintOut("hello world");
                TraceMessage("End of Main");
            }
        }

    被标注了Obsolete的程序结构会被标注为过期,但代码仍然可以正常运行,只是编译时显示对应的过期警告提示,如果想不删除这个程序结构但也不希望任何人使用,则提供:

    [Obsolete("This method is obsolute",true)]

    它会在编译时显示该程序结构的调用是错误的。

    被标注了Conditional("xx")的程序结构会在编译时被编译器跳过,除非在using上面定义宏

    #define Dotrace

    3、调用者信息特性

            static void MyTrace(string message,[CallerFilePath]string fileName="",[CallerLineNumber]int lineNumber=0,[CallerMemberName]string callingMember="")
            {
                Console.WriteLine("File:{0}", fileName);
                Console.WriteLine("Line:{0}", lineNumber);
                Console.WriteLine("Called From:{0}", callingMember);
                Console.WriteLine("Message:{0}", message);
            }
    ...
    MyTrace("Simple message");

    File:E:StudyC#ConceptsAttributeAttributeProgram.cs
    Line:33
    Called From:Main
    Message:Simple Message

    CallerFilePath,CallerLineNumber,CallerMemberName用于访问文件路径、代码行数、调用成员的名称等源代码信息,但这些特性智能用于方法中的可选参数。

    4、调试时跳过某些代码

    [DebugStepThrough]

    5、序列化

     [Serializable]特性本身并不序列化,它只是指示这个对象可以被序列化。

    6、自定义特性

    要声明一个自定义特性,需要作如下工作:

    A、声明一个派生自System.Attribute的类,通常还带有sealed保证安全性

    B、起一个带有Attribute作为后缀的名字

    C、能持有的公共成员只能是字段、属性、构造函数

        
        [AttributeUsage(AttributeTargets.Class)]
    public sealed class MyAttributeAttribute:System.Attribute { public string Description { get; set; } public string Version { get; set; } public MyAttributeAttribute(string desc,string version) { Description = desc; Version = version; } }
        [Serializable]
        [MyAttribute("Class Attribute","Version 1.0.0")]
        class Attribute
        {
            public int Id { get; set; }
        }

    在使用自定义特性时,应注意以下实践:

    1、特性类应该标识目标结构的一些状态

    2、如果特性需要某些字段,可以通过包含具有位置参数的构造函数来收集数据,可选字段可以采用命名参数来按需初始化。

    3、除了属性外,不实现公共方法或其他函数成员

    4、特性类声明为密封类

    5、在特性声明中使用AttributeUsage来显式指定特性目标组

    可以通过Type对象的IsDefined来检查某个特性是否应用到了某个类上。

                Type t = attribute.GetType();
                bool isDefined = t.IsDefined(typeof(MyAttributeAttribute), false);
                if (isDefined)
                    Console.WriteLine($"MyAttribute is applied to type {t.Name}");       

    输出:MyAttribute is applied to type Attribute

    也可以:

                object[] attrArr = t.GetCustomAttributes(false);
                foreach(MyAttributeAttribute item in  attrArr)
                {
                    MyAttributeAttribute attr = item as MyAttributeAttribute;
                    if(null!=attr)
                    {
                        Console.WriteLine($"Decription:{attr.Description}");
                        Console.WriteLine($"Version:{attr.Version}");
                    }
    
                }

    输出:

    Decription:Class Attribute
    Version:Version 1.0.0

  • 相关阅读:
    android gridview布局,实现长按某一个,所有项都显示删除的图标
    Error:Execution failed for task ':app:transformClassesWithDexForDebug&#
    FragmentActivity和Activity的具体区别在哪里
    android批量文件上传(android批量图片上传)
    Android studio修改debug.keystore
    2 weekend110的SecureCRTPortable远程连接 + 上传安装jdk + 上传安装配置hadoop
    1 weekend110的Linux带图形系统安装 + 网络配置 + 静态IP设置
    weekend110(Hadoop)的 第一天笔记
    详细讲解Hadoop源码阅读工程(以hadoop-2.6.0-src.tar.gz和hadoop-2.6.0-cdh5.4.5-src.tar.gz为代表)
    如何自己编译生成hadoop的eclipse插件,如hadoop-eclipse-plugin-2.6.0.jar
  • 原文地址:https://www.cnblogs.com/NicolasLiaoran/p/12967893.html
Copyright © 2011-2022 走看看