C#中Attribute特性的用法

开篇语

本文开始之前,首先我想问下大家对于属性和特性知道多少?属性和特性又有何区别?

对于该单词,我更想把它称之为:特性。对于属性和特性就是名称上有纠葛(不知道你们迷不迷,反正我写本文之前我是迷了),什么是属性?属性是面向对象编程的基本概念,提供了对私有字段的访问封装,在C#中以get和set访问器方法实现对可读可写属性的操作,提供了安全和灵活的数据访问封装。什么是特性?下面内容就说明下:

介绍

使用特性,可以有效地将元数据或声明性信息与代码(程序集、类型、方法、属性等)相关联。将特性与程序实体相关联后,可以在运行时使用 反射 这项技术查询特性。详情 用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性。

简单总结:定制特性attribute,本质上是一个类,其为目标元素提供关联附加信息,并在运行期以反射的方式来获取附加信息。

常用特性 AttributeUsage

AttributeUsage特性用于控制如何应用自定义特性到目标元素,有三个数据属性可用以修饰我们的自定义的属性

ValidOn规定特性可被放置的语言元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
AllowMultiple定义了是否可在同一个程序实体上同时使用多个属性进行修饰
Inherited定义了自定义属性的修饰是否可由被修饰类的派生类继承
[AttributeUsage(validOn: AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public class HelpAttribute : Attribute { }

表示该特定只能标识在类上,并且同一个类上只能用一个属性修饰,并且自定义属性的修饰不能由修饰类的派生类继承。

Flags

以Flags特性来将枚举数值看作位标记,而非单独的数值,例如我有如下的一个需求,当我想要取得用户信息的时候,会先从本地缓存中查找,找不到然后从分布式缓存中查找,最后找不到再从数据库中查询。但是有些场景我又不需要查询数据库。

所以会建立下面的这种模型

public UserEntity GetUserInfo(List<DataSource> dataSources) { var xxxx = new UserEntity(); if(dataSources.Any(DataSource.Local) { //从本地缓存中获取 return xxxx; } if(dataSources.Any(DataSource.Distribution) { //从分布式缓存中获取 //更新本地缓存 return xxxx; } if(dataSources.Any(DataSource.DB) { //从DB中获取 //更新分布式缓存 //更新本地缓存 } return xxxx; }

但是每次调用者都去构建一个List,比较麻烦,此时我们可以使用枚举中的Flags特性,修改程序如下:

首先是枚举的定义上,要加上 [Flags] 特性标签,并且定义 一般都是 2的n次方,主要是便于位移运算

/// <summary> ///数据取得地方 /// </summary> [Flags] public enum DataSource { /// <summary> ///本地缓存 /// </summary> [Description("本地缓存")] LocalCache = 1, /// <summary> ///分布式缓存 /// </summary> [Description("分布式缓存")] DistributeCache = 2, /// <summary> ///数据库 /// </summary> [Description("数据库")] DB = 4, }

修改代码

public UserEntity GetUserInfo(DataSource dataSources) { var xxxx = new UserEntity(); if(dataSources.HasFlags(DataSource.Local) { //从本地缓存中获取 return xxxx; } if(dataSources.HasFlags(DataSource.Distribution) { //从分布式缓存中获取 //更新本地缓存 return xxxx; } if(dataSources.HasFlags(DataSource.DB) { //从DB中获取 //更新分布式缓存 //更新本地缓存 } return xxxx; }

调用的地方,可以用过“|”来指定,例如我只想用分布式缓存和数据库,那么:

var userInfo = GetUserInfo(DataSource.Distribution | DataSource.DB);

该例子摘抄自:https://www.jb51.net/article/254408.htm

DllImport

DllImport特性,可以让我们调用非托管代码,所以我们可以使用DllImport特性引入对Win32 API函数的调用

[System.Runtime.InteropServices.DllImport("user32.dll")] extern static void SampleMethod(); Serializable

Serializable特性表明了应用的元素可以被序列化(serializated)

[Serializable] public class SampleClass { // Objects of this type can be serialized. } Conditional

Conditional特性,用于条件编译,在调试时使用。注意:Conditional不可应用于数据成员和属性。

自定义特性

可通过定义特性类创建自己的自定义特性,特性类是直接或间接派生自 Attribute 的类,可快速轻松地识别元数据中的特性定义。假设我们希望使用编写类的程序员名字来标记该类,那么我们就需要自定义一个Author特性类

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] public class AuthorAttribute : Attribute { public string AuthorName; public double version; public AuthorAttribute(string authorName) { this.AuthorName = authorName; version = 1.0; } }

类名 AuthorAttribute 是该特性的名称,即 Author 加上 Attribute 后缀。由于该类继承自 System.Attribute,因此它是一个自定义特性类。构造函数的参数是自定义特性的位置参数。在此示例中,name 是位置参数。所有公共读写字段或属性都是命名参数。在本例中,version 是唯一的命名参数。

请注意,使用 AttributeUsage 特性可使 Author 特性仅对类和 struct 声明有效。

可按照下面的方式使用特性

[Author("张三", version = 1.1)] [Author("李四", version = 1.2)] public class SampleClass { // 业务逻辑代码 }

获取自定义参数

var attr = typeof(SampleClass).GetCustomAttributes(typeof(AuthorAttribute), true);

GetCustomAttributes 会以数组形式返回 Author 对象和任何其他特性对象

推荐阅读

    foreach的用法c语言和c#

    foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语言和c#详细讲解foreach循环的用法C#中的foreach 怎么用啊foreach用法C#中的f

    params 是什么意思,c#里

    params 是什么意思,c#里,参数,数组,本文目录params 是什么意思,c#里params.add跟params.put有区别吗C#中ref,out和params有什么区别发送请

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session

    C# 基于StackExchange.Redis.dll利用Redis实现分布式Session,令牌,客户端,最近在研发一款O2O产品,考虑到分布式架构的需要,以前那一套.NET的

    c#中 (ToolStrip

    c#中 (ToolStrip,窗体,控件,本文目录c#中 (ToolStrip)控件是做什么用的winform窗体问题 toolstrip怎么重用,每个窗体都要用到同样的工具栏窗体

    C#取得DataTable最大值、最小值

    C#取得DataTable最大值、最小值,最大值,最小值,C#取得DataTable最大值、最小值int max=int.Parse((dtItemsAll.Compute("Max(CPITEMS_SOR

    C#如何打印|cctv5体育节目表

    C#如何打印|cctv5体育节目表,,C#如何打印最省事的办法,引用word对象,再把word弹出来用word打印,比较适合你这样刚学的,还不容易出错。cctv5体

    C#中的listview控件怎么用

    C#中的listview控件怎么用,控件,第一个,C#中的listview控件怎么用比如你在窗体上放了一个ListView,教你一些简单的操作。listView1.Columns