【.NET Core】特性(Attribute)详解

news/2024/5/19 23:24:20 标签: .netcore, linq, c#, asp.net, 开发语言

【.NET Core】特性(Attribute)详解

文章目录

  • 【.NET Core】特性(Attribute)详解
    • 一、概述
    • 二、编写自定义属性
      • 2.1 自定义特性的主要步骤
      • 2.2 应用AttributeUsageAttribute
        • AttributeTargets 成员
        • Inherited属性
        • AllowMultiple属性
    • 三、声明特性类
    • 四、声明构造函数特性类
    • 五、声明属性的特性类
    • 六、自定义特性示例
    • 七、总结
    • 八、参考

一、概述

公共语言运行时添加类的关键描述性声明(称为特性),以便批注编程元素(如类型、字段、方法和属性)。编译运行时的代码时,它将被转换为中间语言(MSIL),并和编译器生成的元数据一起放置在可移植可执行文件内。特性使得将额外的描述信息放到可使用运行时反射服务提取的元数据中。当你声明派生自System.Attribute 的特殊类的实例时,编译器会创建特性。

在.NET内置了很多特性,这些特性描述数据序列化、指定用于强制安全性的特性并限制通过实时(JIT)编译器进行优化,来对代码进行调优。

二、编写自定义属性

2.1 自定义特性的主要步骤

  1. 应用AttributeUsageAttribute
  2. 声明特性类
  3. 声明构造函数
  4. 声明属性

2.2 应用AttributeUsageAttribute

自定义属性声明以System.AttributeUsageAttribute属性开头,定义特性类的一些主要特性。

AttributeUsageAttribute包含下列三个成员,它们对创建自定义属性非常重要:AttributeTargetsInheitedAllowMultiple

AttributeTargets 成员
成员说明
All32767属性可以应用于任何应用程序元素。
Assembly1属性可应用于程序集。
Class4属性可应用于类。
Constructor32属性可应用于构造函数。
Delegate4096属性可应用于委托。
Enum16属性可应用于枚举。
Event512属性可应用于事件。
Field256属性可应用于字段。
GenericParameter16384属性可应用于泛型参数。目前,这个属性只能在C#,Micrsoft中间语言(MSIL)和emitted代码中。
Interface1024属性可应用于接口。
Method64属性可应用于方法。
Module2属性可应用于模块。模块指的是可移植的执行文件(.dll或.exe),而不是Visual Basic标准模块。
Parameter2048属性可应用于参数。
Property128属性可应用于属性。
ReturnValue8192属性可应用于返回值。
Struct8属性可应用于结构;也就是值类型。
Inherited属性

AttributeUsageAttribute.Inherited属性指明要对其应用属性的类的派生类能否继承此属性。此属性使用true(默认值)或false标志。

c#">public class MyAttribute : Attribute
{
    //...
}
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class YourAttribute : Attribute
{
    //...
}
AllowMultiple属性

AttributeUsageAttribute.AllowMultiple属性指明元素能否包含属性的多个实例。如果设置为true,则允许多个实例。如设置为false(默认值),那么只允许一个实例。

c#">/// <summary>
/// AllowMultiple =false 不允许多个属性
/// </summary>
[AttributeUsage(AttributeTargets.Method,AllowMultiple =false)]
public class MyAttribute:Attribute
{
    ///方法体
}
/// <summary>
/// AllowMultiple =false 允许多个属性
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MultipleMyAttribute : Attribute 
{
    ///方法体
}

当应用这些特性的多个实例时,MyAttribute会生成编译器错误吗。以下代码示例显示MultipleMyAttribute的有效以及MyAttribute无效用法:

c#">public class AttributeService
{
    // This produces an error.
    // Duplicates are not allowed.
    [MyAttribute()]
    [MyAttribute()]
    public void Get() {}
    // This is valid.
    [MultipleMy]
    [MultipleMy]
    public void Update() { }
}

如果AllowMultiple属性和Inherited属性都设置为true,从另一个类继承的类可以继承一个属性,并具有在同一个子类中应用相同属性的另一个实例。如果AllowMultiple设置为false,则父类中的所有特性的值将被子类中一特性的新实例覆盖。

三、声明特性类

应用AttributeUsageAttribute以后,开始定义属性的细节。特性类的声明类似与传统类的声明。如以下代码所示:

c#">[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple =false)]
public class MyAttribute:Attribute
{
    ///
}

此特性定义说明了以下几点:

  • 特性类必须声明为公共类。
  • 按照约定,特性类的名称以单词Attribute结束。官方虽然没有要求,但是扔建议执行此约定以保证可读性。应用特性时,可以选择是否包含单词Attribute
  • 所有特性类必须直接或间接从System.Attribute类继承。

四、声明构造函数特性类

和传统类类似,特性是通过构造函数初始化的。下面的代码段阐明了典型的特性构造函数。此公共构造函数采用一个参数,并设置一个等于其值的成员变量。

c#">[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple =false)]
public class MyAttribute:Attribute
{
    private string myValue;
    public MyAttribute(string myValue)
    {
        this.myValue = myValue;
    }
}

可以重载此构造函数以适应值的各种组合。如果你还未自定义特性类定义了属性,则在初始化该特性时可以使用命名参数和定位参数的组合。通常情况下,将所有必须的参数定义为定位参数,将所有可选的参数定义为命名参数。在这种情况下,没有必需的参数就无法初始化属性。其他所有参数都是可选参数。

五、声明属性的特性类

如果你想要定义一个命名参数,或者提供一种简单的方法来返回由特性存储的值,请声明属性。应将特性的属性声明为公共实例,此公告实体包含将返回的数据类型的描述。定义将保存属性值的变量,并将此变量与get和set方法相关联。

c#">[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple =false)]
public class MyAttribute:Attribute
{
    public string AttributeName 
    {
        get; 
        set;
    } 
}

六、自定义特性示例

c#">[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,AllowMultiple =false)]
public class MyAttribute:Attribute
{
    private string author;
    private DateTime data;
    private string version;
    public MyAttribute(string author, DateTime data)
    {
        this.author = author;
        this.data = data;
    }

    public virtual string Author 
    {
         get { return author; }
    }

    public virtual DateTime Data 
    {
        get { return data; }
    }

    public string Version 
    {
       get { return version; }
       set { version = value; }
    }
}

可以采用以下任意一种方法,调用自定义特性:

c#">public class AttributeService
{
    [MyAttribute("AuthorName","2023-12-18 15:14:01")]
    public void Get(){}
    [MyAttribute("Author2","2023-12-18 16:14:49",Version="v1.0")]
    public void Update() { }     
}

七、总结

特性提供声明式编程能力,但是它们是一种元数据形式的代码,本身并不执行任何操作。可以通过反射来调用特性完成操作。

下一章将详解如何使用反射调用特性。

八、参考

  1. [利用特性扩展元数据](利用特性扩展元数据 | Microsoft Learn)
  2. [应用属性](应用特性 - .NET | Microsoft Learn)
  3. [编写自定义属性](编写自定义特性 - .NET | Microsoft Learn)

http://www.niftyadmin.cn/n/5273394.html

相关文章

Java中的跨站脚本攻击(XSS)处理技术

Java中的跨站脚本攻击&#xff08;XSS&#xff09;处理技术 文章目录 Java中的跨站脚本攻击&#xff08;XSS&#xff09;处理技术[TOC] 一、引言二、XSS攻击原理三、Java中的XSS防范措施四、XSS攻击的检测和预防五、代码示例六、总结 一、引言 跨站脚本攻击&#xff08;XSS&am…

【C++】POCO学习总结(十九):哈希、URL、UUID、配置文件、日志配置、动态库加载

【C】郭老二博文之&#xff1a;C目录 1、哈希 1.1 说明 std::map和std::set 的性能是&#xff1a;O(log n) POCO哈希的性能比STL容器更好&#xff0c;大约快两&#xff1b; POCO中对应std::map的是&#xff1a;Poco::HashMap&#xff1b; POCO中对应std::set的是 Poco::Hash…

Windows11编译x265源码生成Visual Studio工程详细步骤

概述 x265是一款开源符合HEVC标准的编码器&#xff0c;也属于VLC项目之一。 由于x265是开源的&#xff0c;因此它得到了广泛的应用和开发。许多开源项目和商业产品都使用x265进行视频压缩处理。同时&#xff0c;x265也支持多种编程语言和平台&#xff0c;使得开发者可以方便地…

数据分析场景下,企业大模型选型的思路与建议

来源/作者&#xff1a;爱分析 随着大模型带来能力突破&#xff0c;让AI与数据分析相互结合&#xff0c;使分析结果更好支撑业务&#xff0c;促进企业内部数据价值释放&#xff0c;成为了当下企业用户尤为关注的话题。本次分享主要围绕数据分析场景下大模型底座的选型思路&#…

Docker使用5-Use bind mounts

写在前面 主题是Use bind mounts&#xff0c;这里是链接。本文主要学习持久化数据的另一种方式。 使用mount持久化数据 前文使用Volume持久化数据&#xff0c;这里使用另一种方式Mount持久化数据&#xff0c;就是把主机中的路径映射到容器内的路径。下图是两种方式的主要区别…

5路开关量转继电器 Modbus TCP远程I/O模块 YL95 RJ-45网络接口通信

特点&#xff1a; ● 五路开关量输入&#xff0c;五路继电器输出 ● 支持Modbus TCP 通讯协议 ● 内置网页功能&#xff0c;可以通过网页查询电平状态 ● 可以通过网页设定继电器输出状态 ● DI信号输入&#xff0c;DO输出及电源之间互相隔离 ● 宽电源供电范围&#x…

【PHP入门】2.1-运算符

-运算符- 运算符&#xff1a;operator&#xff0c;是一种将数据进行运算的特殊符号&#xff0c;在PHP中一共有十种运算符之多。 2.1.1赋值运算符 赋值运算&#xff1a;符号是“”&#xff0c;表示将右边的结果&#xff08;可以是变量、数据、常量和其它运算出来的结果&#…

Docker单点部署[8.11.3] Elasticsearch + Kibana + ik分词器

文章目录 一、Elasticsearch二、Kibana三、访问四、其他五、ik分词器第一种&#xff1a;在线安装第二种&#xff1a;离线安装 Elasticsearch 和 Kibana 版本一般需要保持一致才能一起使用&#xff0c;但是从 8.x.x开始&#xff0c;安全验证不断加强&#xff0c;甚至8.x.x之间…