• 特性--反射


    1.概述

            特性(Attribute)是一种将自定义信息添加到代码元素(程序集、类型、成员、返回值、参数和泛型类型参数)的扩展机制。

    2. 特性类

            特性是通过直接或者间接继承抽象类System.Attribute的方式定义的。

            如果要将一个特性附加到一个代码元素中,那么就需要在该代码元素之前用方括号指定特性的类型名称。

    1. using NPOI.SS.Formula.Functions;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Linq;
    6. using System.Reflection;
    7. using System.Text;
    8. namespace ConsoleApp1
    9. {
    10. class Program
    11. {
    12. static void Main(string[] args)
    13. {
    14. }
    15. }
    16. //所有特性类型都以Attribute结尾。C#能够识别这个后缀并允许在为成员附加特性时忽略该后缀
    17. //ObsoleteAttribute 适用于除程序集、模块、参数和返回值之外的所有程序元素。 将元素标记为已过时通知用户,在产品的未来版本中可能会删除该元素。
    18. [ObsoleteAttribute]
    19. public class Foo
    20. {
    21. }
    22. }

    3. 命名和位置特性参数

            特性可以包含参数。

            特性参数分为两类:位置参数和命名参数。第一个参数是位置参数,第二个参数是命名参数。位置参数对应于特性类型的公有构造器的参数;命名参数则对应于该特性类型的公有字段或者公有属性。
            当指定一个特性时,必须包含对应特性构造器中的位置参数,而命名参数则是可选的。

    【问题1】如何通过特性使程序代码符合CLS

            CLSCompliantAttribute 类:指示程序元素是否符合公共语言规范 (CLS)。 此类不能被继承。

            该 CLSCompliantAttribute 属性用于指示特定程序元素是否符合公共语言规范 (CLS) ,后者定义面向 .NET 的任何语言必须支持的功能。

    解答:

            通过在程序集中声明[assembly: CLSCompliant(true)]特性即可保证整个程序集代码必须遵守CLS,否则编译时将报错。如果程序集代码中某些元素(如属性)需要逃避符合 CLS的检查,可添加[property: CLSCompliant(false)]特性注释。

     

     

    分析:

            CLS 即公共语言规范,它保证了整个应用程序可以无缝跨越.NET 的各种语言。例如C#中的多个相同字母组合的标识符可以通过字母大小写不同区分,但是VB.NET则视为非法,C#的这种做法则被称为没有遵守 CLS。在程序集中声明[CLSCompliant]特性即可保证编译时检查程序集代码是否遵守CLS,以利于其他.NET语言的调用。         

    1. //可声明整个程序集必须遵守CLS
    2. [assembly: CLSCompliant(true)]
    3. //可声明被注释的属性可以不遵守CLS,即可正常通过编译
    4. [property: CLSCompliant(false)]
    5. //可声明被注释的方法可以不遵守CLS,即可正常通过编译
    6. [method: CLSCompliant(false)]

    【问题2】  如何使用特性编译时给出警告

            只需在类或成员前面注释[Obsolete]特性,一旦主程序中使用了该类或成员,可以在编译时给出警告。

     

    分析:

            [Obsolete]特性在团队合作时非常有用,它可以帮助程序员选择性地使用某些调试中的类或方法。[Obsolete]特性的编写方法如以下代码所示:

    1. [Obsolete("警告文本")]
    2. 被注释项(一般为类或成员)
    3. [Obsolete]特性的参数为string类型,即可作为在编译时警告的说明文本。 

    【问题3】 如何自定义特性 

            自定义特性需定义一个System.Attribute类的派生类,才可以在程序中使用。

    1. using System;
    2. namespace ConsoleApp1
    3. {
    4. class Program
    5. {
    6. static void Main(string[] args)
    7. {
    8. var bc = new BaseClass();
    9. Console.WriteLine(bc.BaseField);
    10. var dc = new DerivedClass();
    11. BaseClass[] bca = new BaseClass[] { dc, bc };
    12. foreach (var v in bca)
    13. {
    14. Console.WriteLine("object type:{0}", v.GetType().Name);
    15. var fi = v.GetType().GetFields();
    16. Console.WriteLine($"IsDefined:{v.GetType().Name}:{v.GetType().IsDefined(typeof(ReviewCommentAttribute), false)}");
    17. foreach (var f in fi)
    18. {
    19. Console.WriteLine("Field:{0}", f.Name);
    20. }
    21. }
    22. var t = dc.GetType();
    23. var Attrs = t.GetCustomAttributes(true);
    24. foreach (var attr in Attrs)
    25. {
    26. var attr1 = attr as ReviewCommentAttribute;
    27. Console.WriteLine($"{attr1.IsValid()}");
    28. }
    29. }
    30. }
    31. //特性也可被限制使用范围,只需在自定义特性类前面添加[AttributeUsage]特性
    32. //[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field,AllowMultiple =true,Inherited = false)]
    33. //该特性第1个参数为 AttributeTargets 枚举值,以上代码为自定义特性仅允许用于类(Class)和字段(Field)。
    34. //第2个参数AllowMultiple代表在相同元素上是否可以注释多次。第3个参数代表是否可被派生类继承。
    35. [AttributeUsage(AttributeTargets.Class| AttributeTargets.Field)]
    36. public sealed class ReviewCommentAttribute : System.Attribute
    37. {
    38. public string Description { get; set; }
    39. public string VersionNumber { get; set; }
    40. public string ReviewerID { get; set; }
    41. public ReviewCommentAttribute(string desc, string ver)
    42. {
    43. Description = desc;
    44. VersionNumber = ver;
    45. }
    46. public bool IsValid()
    47. {
    48. if (ReviewerID.GetType().Name.Equals("String"))
    49. {
    50. return true;
    51. }
    52. return false;
    53. }
    54. }
    55. class BaseClass
    56. {
    57. [ReviewCommentAttribute("","", ReviewerID="111")]
    58. public int BaseField = 0;
    59. }
    60. [ReviewComment("This is Derived", "0.8.1", ReviewerID="111")]
    61. class DerivedClass : BaseClass
    62. {
    63. public int DerivedField = 0;
    64. }
    65. }

    分析:

            特性实际是System.Attribute类的派生类,所以自定义特性需要定义以System.Attribute类为基类的特性类,如以下代码所示:

    1. using System.;
    2. public class 自定义特性类名称 : Attribute
    3. {
    4. 类体代码;
    5. }

  • 相关阅读:
    哈希表 | 基础知识总结
    使用 shell 脚本自动获取发版指标数据
    SpringBoot整合JWT实现登陆验证
    7. 矢量图层数据查询选择和保存
    常用类--String
    JavaScript While循环
    SpringSecurity(三)- SpringSecurity 原理
    聊聊Mybatis的SqlSession
    算法竞赛入门【码蹄集进阶塔335题】(MT2291-2295)
    面试官:RocketMQ是什么,它有什么特性与使用场景?
  • 原文地址:https://blog.csdn.net/Abel_01_xu/article/details/126010965