windows C#-定义和读取自定义特性

news2024/11/29 22:31:15

使用特性,可以声明的方式将信息与代码相关联。 特性还可以提供能够应用于各种目标的可重用元素。 考虑 ObsoleteAttribute。 它可以应用于类、结构、方法、构造函数等。 用于声明元素已过时。 然后,由 C# 编译器负责查找此特性,并执行某响应操作。

此教程介绍如何将特性添加到代码中、如何创建和使用你自己的特性,以及如何使用一些内置到 .NET 中的特性。

创建应用

安装所有工具后,创建一个新的 .NET 控制台应用。 若要使用命令行生成器,请在常用的命令行管理程序中执行以下命令:

dotnet new console

此命令将创建最基本的 .NET 项目文件。 运行 dotnet restore 以还原编译此项目所需的依赖项。

无需运行 dotnet restore,因为它由所有需要还原的命令隐式运行,如 dotnet new、dotnet build、dotnet run、dotnet test、dotnet publish 和 dotnet pack。 若要禁用隐式还原,请使用 --no-restore 选项。

在执行显式还原有意义的某些情况下,例如 dotnet restore中,或在需要显式控制还原发生时间的生成系统中,dotnet restore 命令仍然有用。

若要运行程序,请使用 dotnet run。 此时,应该可以在控制台中看到“Hello, World”输出。

将特性添加到代码中

在 C# 中,特性是继承自 Attribute 基类的类。 所有继承自 Attribute 的类都可以用作其他代码块的一种“标记”。 例如,有一个名为 ObsoleteAttribute 的特性。 此特性示意代码已过时,不得再使用。 将此特性应用于类(比如说,使用方括号)。

[Obsolete]
public class MyClass
{
}

虽然此类的名称为 ObsoleteAttribute,但只需在代码中使用 [Obsolete]。 大多数 C# 代码都遵循此约定。 如果愿意,也可以使用全名 [ObsoleteAttribute]。

如果将类标记为已过时,最好说明已过时的原因和/或改用的类。 在“已过时”特性中包含字符串参数以提供此说明。

[Obsolete("ThisClass is obsolete. Use ThisClass2 instead.")]
public class ThisClass
{
}

此字符串会作为参数传递给 ObsoleteAttribute 构造函数,就像在编写 var attr = new ObsoleteAttribute("some string") 一样。

只能向特性构造函数传递以下简单类型/文本类型参数:bool, int, double, string, Type, enums, etc和这些类型的数组。 不能使用表达式或变量。 可以使用任何位置参数或已命名参数。

创建你自己的特性

通过定义继承自 Attribute 基类的新类来创建特性。

public class MySpecialAttribute : Attribute
{
}

通过上述代码,可在基本代码中的其他位置将 [MySpecial](或 [MySpecialAttribute])用作特性。

[MySpecial]
public class SomeOtherClass
{
}

.NET 基类库中的特性(如 ObsoleteAttribute)会在编译器中触发某些行为。 不过,你创建的任何特性只作元数据之用,并不会在执行的特性类中生成任何代码。 是否在代码的其他位置使用此元数据由你自行决定。

这里要注意的是“gotcha”。 如前所述,使用特性时,只可将某些类型作为参数传递。 不过,在创建特性类型时,C# 编译器不会阻止你创建这些参数。 在以下示例中,你使用可正常编译的构造函数创建了一个特性。

public class GotchaAttribute : Attribute
{
    public GotchaAttribute(Foo myClass, string str)
    {
    }
}

不过,无法将此构造函数与特性语法结合使用。

[Gotcha(new Foo(), "test")] // does not compile
public class AttributeFail
{
}

上述代码导致一个编译器错误,例如 Attribute constructor parameter 'myClass' has type 'Foo', which is not a valid attribute parameter type。

如何限制特性使用

特性可用于以下“目标”。 前面的示例展示了特性在类上的使用情况,而特性还可用于:

  • 程序集
  • 构造函数
  • 委托
  • 枚举
  • 事件
  • 字段
  • 泛型参数
  • 接口
  • 方法
  • 模块
  • 参数
  • properties
  • 返回值
  • 结构

创建特性类时,C# 默认允许对所有可能的特性目标使用此特性。 如果要将特性限制为只能用于特定目标,可以对特性类使用 AttributeUsageAttribute 来实现。 没错,就是将特性应用于特性!

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class MyAttributeForClassAndStructOnly : Attribute
{
}

如果尝试将上述特性应用于不是类也不是结构的对象,你会得到类似 Attribute 'MyAttributeForClassAndStructOnly' is not valid on this declaration type. It is only valid on 'class, struct' declarations 的编译器错误:

public class Foo
{
    // if the below attribute was uncommented, it would cause a compiler error
    // [MyAttributeForClassAndStructOnly]
    public Foo()
    { }
}
如何使用附加到代码元素的特性

特性只作元数据之用。 不借助一些外在力量,特性其实什么用也没有。

若要查找特性并对其进行操作,需要使用反射。 通过反射,能够以 C# 编写检查其他代码的代码。 例如,可以使用反射获取类的相关信息(在代码开始处添加 using System.Reflection;):

TypeInfo typeInfo = typeof(MyClass).GetTypeInfo();
Console.WriteLine("The assembly qualified name of MyClass is " + typeInfo.AssemblyQualifiedName);

输出如下内容:The assembly qualified name of MyClass is ConsoleApplication.MyClass, attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

获取 TypeInfo 对象(或 MemberInfo、FieldInfo 或其他对象)后,就可以使用 GetCustomAttributes 方法了。 此方法返回 Attribute 对象的集合。 还可以使用 GetCustomAttribute 并指定特性类型。

下面的示例展示了对 MyClass(在上文中,它包含 [Obsolete] 特性)的 MemberInfo 实例使用 GetCustomAttributes。

var attrs = typeInfo.GetCustomAttributes();
foreach(var attr in attrs)
    Console.WriteLine("Attribute on MyClass: " + attr.GetType().Name);

输出到控制台:Attribute on MyClass: ObsoleteAttribute。 请尝试向 MyClass 添加其他特性。

请务必注意,这些 Attribute 对象的实例化有延迟。 也就是说,只有使用 GetCustomAttribute 或 GetCustomAttributes,它们才会实例化。 这些对象每次都会实例化。 连续两次调用 GetCustomAttributes 返回两个不同的 ObsoleteAttribute 实例。

运行时中的常见特性

许多工具和框架都会使用特性。 NUnit 和 NUnit 测试运行程序都使用 [Test] 和 [TestFixture] 之类的特性。 ASP.NET MVC 使用 [Authorize] 之类的特性,并提供可密切关注 MVC 操作的操作筛选器框架。 PostSharp 使用特性语法,支持在 C# 中进行面向特性的编程。

下面介绍了一些值得注意的 .NET Core 基类库内置特性:

[Obsolete]。 此特性已在上面的示例中使用过,位于 System 命名空间中。 可用于提供关于不断变化的基本代码的声明性文档。 可以提供字符串形式的消息,并能使用另一布尔参数将编译器警告升级为编译器错误。
[Conditional]。 此特性位于 System.Diagnostics 命名空间中。 可应用于方法(或特性类)。 必须向构造函数传递字符串。 如果该字符串与 #define 指令不匹配,则 C# 编译器将删除对该方法(而不是方法本身)的所有调用。 通常,使用此方法进行调试(诊断)目的。
[CallerMemberName]。 此特性可应用于参数,位于 System.Runtime.CompilerServices 命名空间中。 CallerMemberName 特性用于插入正在调用另一方法的方法的名称。 这是在各种 UI 框架中实现 INotifyPropertyChanged 时清除“神奇字符串”的一种方式。 示例:

public class MyUIClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    public void RaisePropertyChanged([CallerMemberName] string propertyName = default!)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private string? _name;
    public string? Name
    {
        get { return _name;}
        set
        {
            if (value != _name)
            {
                _name = value;
                RaisePropertyChanged();   // notice that "Name" is not needed here explicitly
            }
        }
    }
}

在上面的代码中,无需使用文本类型 "Name" 字符串。 使用 CallerMemberName 可防止出现与拼写错误相关的 bug,也可以让重构/重命名操作变得更加顺畅。 特性为 C# 带来了声明性能力,但它们是一种元数据形式的代码,本身并不执行操作。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2250042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

格网法计算平面点云面积(matlab版本)

1、原理介绍 格网法计算平面点云面积,其思想类似高中油膜法计算面积。其将点云投影到水平面,再将点云划分成尺寸相同的格网。最后,统计格网内包含点的数量number,那么可利用如下公式计算得到点云的面积: Aeranumber*L…

无代码实现可视化GIS+模型+三维

现在的工具是越来越方便了,本来不是做前端的。可以节省很多的人力和时间,更快的搭建自己想要的可视化大屏,看例子 主要由三维的gis地图和模型加上二维的数据表格分析来实现这个可视化界面。 gis地图的设置 每一个gis都要设置世界远点&#x…

Jmeter中的监听器

3)监听器 1--查看结果树 用途 调试测试计划:查看每个请求的详细信息,帮助调试和修正测试计划。分析响应数据:查看服务器返回的响应数据,验证请求是否成功。检查错误:识别和分析请求失败的原因。 配置步骤…

kafka进阶_3.消费消息

文章目录 一、消费消息概览1.1、消费示例代码1.2、消费过程 二、消费者组2.1、push & pull2.2、消费者组 三、调度器Coordinator四、消费者分配策略4.1、引言4.2、分配基本流程4.3、分配策略4.3.1、轮询分配策略4.3.2、轮询分配策略 五、消费偏移量5.1、起始偏移量5.2、指定…

用VC2019+MFC 创建一个DLL封装MD工业相机库然后用EXE调用这个相机库采图并且显示

主要描述: 用VC2019MFC 创建一个DLL封装MD工业相机库,再建一个EXE调用这个相机库采图并且显示。 先创建库工程: 新建一个库工程, 创建完成,添加一个DllFunction.h头文件,一个DllFunction.cpp 源文件 拷贝…

ODB 框架

目录 概述 基本工作原理 映射C对象到数据库表 从数据库中加载对象 持久化C对象到数据库 ODB常用接口 表创建预处理 #pragma db Object table 数据表属性 id auto column(“xxx”) type("xxx") unique index null default&…

ModuleNotFoundError: No module named ‘_ssl‘ centos中的Python报错

1、检查系统有没有openssl,有的话,就是python安装时没有指定openssl openssl version,有输出版本号就有,没有的话,需要手动安装 下载地址 参见https://www.openssl.org/,包括以下版本: https:/…

小程序-基于java+SpringBoot+Vue的微信小程序养老院系统设计与实现

项目运行 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…

linux高级系统编程之进程

进程 一个正在进行的程序 并行与并发 并行:执行的程序在不同CPU上同时执行 并发:一个CPU,多个进程交替执行,因为交替速度很快,所以从宏观上来看是同时执行的,但是从围观的角度是交替执行的 单道与多道 单道程序设计:所有进程一个一个排队执行,若A阻塞,B只能等待,,即使CPU处于空…

GitHub Copilot革命性更新:整合顶尖AI模型,如何重塑开发体验?

在技术快速发展的今天,代码辅助工具已成为提升开发效率的利器。今天,我们带来了一个激动人心的消息——GitHub Copilot宣布引入多模型选择功能,这不仅是技术上的一次飞跃,更是对开发者工作流程的一次革新。 多模型选择&#xff1a…

AppFlow:支持飞书机器人调用百炼应用

AppFlow:支持飞书机器人调用百炼应用 简介: 本文介绍了如何创建并配置飞书应用及机器人,包括登录飞书开发者后台创建应用、添加应用能力和API权限,以及通过AppFlow连接流集成阿里云百炼服务,最后详细说明了如何将机器…

华为E9000刀箱(HWE9000V2)服务器硬件监控指标解读

随着数据中心规模的不断扩大,服务器的稳定性和可靠性变得尤为重要。华为E9000刀箱(HWE9000V2)作为一款高性能的服务器设备,其硬件状态的实时监控对于保障业务的连续性和系统的稳定运行至关重要。 监控易作为一款专业的IT基础设施监…

GWO-SVMD分解 | Matlab实现GWO-SVMD灰狼算法优化逐次变分模态分解

GWO-SVMD分解 | Matlab实现GWO-SVMD灰狼算法优化逐次变分模态分解 目录 GWO-SVMD分解 | Matlab实现GWO-SVMD灰狼算法优化逐次变分模态分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 GWO-SVMD灰狼算法优化逐次变分模态分解 内有15种用以优化svmd的适应度函数&#…

景联文科技:高质量数据采集标注服务引领AI革新

在当今这个数字化时代,数据已经成为推动社会进步和产业升级的关键资源。特别是在人工智能领域,高质量的数据是训练出高效、精准的AI模型的基础。景联文科技是一家专业的数据采集与标注公司,致力于为客户提供高质量的数据处理服务,…

pycharm添加gitee插件

一、拉取gitee上托管的代码到本地,用pycharm运行 前置条件 1.安装python运行环境 2.安装pycharm 安装:https://blog.csdn.net/m0_65482549/article/details/141394352 1.3.安装git git config --global user.name “" git config --global user.em…

Echarts 绘制地图

一、Apache Echarts 官网地址:https://echarts.apache.org/ npm install echarts --save 二、获取地图的GeoJSON 地址:DataV.GeoAtlas地理小工具系列 左侧是地图,右侧是JSON数据路径,点击你想要生成的地图省市、地级&#xff0…

DHCP服务(包含配置过程)

目录 一、 DHCP的定义 二、 使用DHCP的好处 三、 DHCP的分配方式 四、 DHCP的租约过程 1. 客户机请求IP 2. 服务器响应 3. 客户机选择IP 4. 服务器确定租约 5. 重新登录 6. 更新租约 五、 DHCP服务配置过程 一、 DHCP的定义 DHCP(Dynamic Host Configur…

html+css+js网页设计 旅游 厦门旅游网14个页面

htmlcssjs网页设计 旅游 厦门旅游网14个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&am…

springboot(20)(删除文章分类。获取、更新、删除文章详细)(Validation分组校验)

目录 一、删除文章分类功能。 (1)接口文档。 1、请求路径、请求参数。 2、请求参数。 3、响应数据。 (2)实现思路与代码书写。 1、controller层。 2、service接口业务层。 3、serviceImpl实现类。 4、mapper层。 5、后端接口测试。…

现代化水库可视化管理平台:提升水库运行效率与安全保障

随着科技的飞速发展,现代化水利管理逐渐依赖于数字化、智能化手段。作为水利基础设施的重要组成部分,水库的管理不仅关乎水资源的合理利用,还关系到防洪、灌溉、供水等多项社会功能的实现。为了提升水库的管理水平,确保其运行安全…