行业知识
C# 特性(Attribute)超详细教程
2026-10-27 01:25:17
来源:互联网转载
文章目录
- 0.前篇
- 1.特性概念
- 2.特性的声明和使用
- 2.1 特性定义语法
- 2.2 特性目标
- 3.预定义特性
- 3.1 AttributeUsage
- 3.2 Conditional
- 3.3 其它预定义特性
- 4.MyAttributeHelper(特性使用帮助类)
- 5.特性应用
- 5.1 添加说明信息并获取
- 5.2 数据验证
0.前篇
学习本文前建议先阅读我的关于反射的博文:
()https://editor.csdn.net/md/?articleId=139095147
1.特性概念
特性是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。
()2.特性的声明和使用
2.1 特性定义语法
特性在声明时以Attribute结尾,在使用时可省去Attribute
[attribute(positional_parameters, name_parameter = value, …)]element
参数说明:
- positional_parameters: 表示特性必须具备的信息。
- name_paramete:表示特性可选的信息。
- element: 在这里表示特性目标。
代码示例:
特性声明:
public class TestAttribute : Attribute{ public int Parm { get; set; } private int id; private string name; public TestAttribute() { } public TestAttribute(int id, string name) { this.id = id; this.name = name; }}特性使用:
[Test] // 使用无参构造函数public class TestClass1{}[Test(Parm = 123)] // 使用无参构造函数 + 指定参数public class TestClass2{}[Test(1, "test")] // 使用有参构造函数public class TestClass3{}2.2 特性目标
特性目标指的是应用特性的实体。例如,特性目标可以是类、特定方法或整个程序集。一般情况,特性应用于紧跟在它后面的元素。不过,C# 特性支持显示标识,例如可以显示标识为将特性应用于方法,或者是应用于其参数或返回值。
显示标识特性目标的语法如下:
[target : attribute-list]
- target:表示指定的特性目标值。
- attribute-list:表示要应用的特性列表。
下表展示常用的 target 值:
目标值 适用对象 assembly 整个程序集 module 当前程序集模块 field 类或结构中的字段 event 事件 method 方法或 get 和 set 属性访问器 param 方法参数或 set 属性访问器参数 property Property(属性) return 方法、属性索引器或 get 属性访问器的返回值 type 结构、类、接口、枚举或委托 代码示例:
// 默认: 应用于方法[Test]int Method1(){ return 0; }// 显示指定应用于方法[method: Test]int Method2(){ return 0; }// 应用于参数int Method3([Test] string contract) { return 0; }// 应用于返回值[return: Test]int Method4(){ return 0; }3.预定义特性
3.1 AttributeUsage
特性 AttributeUsage 描述了如何使用一个自定义特性类。注意,使用特性修饰的类 AttributeUsage 必须是 System.Attribute 的直接或间接派生类,否则将发生编译时错误。
AttributeUsage 特性的语法如下:
[AttributeUsage(validon, AllowMultiple = allowmultiple, Inherited = inherited)]
- validon: 表示可被应用的特性目标值。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All。
- AllowMultiple: 可选,allowmultiple 选项为其提供一个布尔值。表示特性是否能被重复放置多次
- Inherited:可选,inherited 选项为其提供一个布尔值。表示 能否被派生类所继承。
示例代码:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]public class ExampleAttribute : Attribute{ public ExampleAttribute(string name) { }}3.2 Conditional
特性 Conditional 是有条件的意思。使用特性修饰的方法也就是条件方法,条件方法的执行依赖于指定的预处理标识符。预处理标识符影响着方法调用的条件编译,这种影响取决于指定的值。例如事先用预处理器指令定义了一个 Test 字符,当条件方法指定的值也为 Test 时, 则该方法会被执行。
语法:
[Conditional(conditionalSymbol)]
- 参数 conditionalSymbol 表示指定的预处理标识符。
#define Testusing System;public class Example{ [Conditional("Test")] static void Method1() { Console.WriteLine("Method1"); } static void Method2() { Console.WriteLine("Method2"); } static void Main() { Method1(); Method2(); }}输出:
Method1Method2
注释掉 #define Test 输出
Method2
3.3 其它预定义特性
特性 说明 [Obsolete] 标记已过时的代码,使得在使用过时成员时发出警告或错误信息。 [Serializable] 用于标记类,表示该类可以序列化,即可以在网络上传输或者在文件中存储。 [DllImport] 用于指示要在程序中调用非托管代码(通常是 DLL)的方法。 [Conditional] 与预处理指令 ‘#if’ 和 ‘#endif’ 结合使用,根据定义的条件编译代码。 [AttributeUsage] 用于指定自定义特性的使用方式,如允许的目标类型和是否允许多次应用等。 [Conditional] 根据条件编译代码,类似于预处理指令,但是使用 Attribute。 [DefaultValue] 为属性或字段设置默认值。 [Description] 为属性或者事件提供一个描述,通常在设计时使用。 4.MyAttributeHelper(特性使用帮助类)
using System.Reflection;namespace Ming.Utils{ public static class MyAttributeHelper { /// /// 获取该类型下所有的带Attribute的方法 /// /// 特性类型 /// /// public static List GetAllMethods(Type type) where T : class, new() { var res = new List(); res = type.GetMethods().Where(t => t.GetCustomAttributes(typeof(T), false).Any()).ToList(); return res; } /// /// 获取该类型下所有的带Attribute的属性 /// /// /// /// public static List GetAllPropertys(Type type) where T : class, new() { var res = new List(); res = type.GetProperties().Where(t => t.GetCustomAttributes(typeof(T), false).Any()).ToList(); return res; } /// /// 获取程序集所有带 T 特性的类class /// /// 特性类型 /// 程序集下所有带 T 特性的类class public static List GetAllTypes() where T : Attribute { var res = new List(); //Assembly存放所有的程序集 res = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => t.GetCustomAttributes(typeof(T), false).Any())//我们找到所有程序集中带有T特性的Type类型 .ToList(); return res; } /// /// 获取类上的特性 /// /// /// /// public static T GetAttribute(Type type) where T : Attribute, new() { var res = new T(); res = type.GetCustomAttribute(); return res; } /// /// 获取方法上的特性 /// /// /// /// public static T GetAttribute(MethodInfo type) where T : Attribute, new() { var res = new T(); res = type.GetCustomAttribute(); return res; } /// /// 获取属性上的特性 /// /// /// /// public static T GetAttribute(PropertyInfo type) where T : Attribute, new() { var res = new T(); res = type.GetCustomAttribute(); return res; } /// /// 返回带有Attribute的类型元祖列表 /// /// /// public static List GetAll_TypeAndAtt() where Att : Attribute, new() { var res = new List (); var typeLists = GetAllTypes(); foreach (var item in typeLists) { var att = GetAttribute(item); res.Add((item, att)); } return res; } /// /// 返回带有Attribute的变量元祖列表 /// /// /// /// public static List GetAll_PropertyAndAtt(Type type) where Att : Attribute, new() { var res = new List(); var typeLists = GetAllPropertys(type); foreach (var item in typeLists) { var att = GetAttribute(item); res.Add((item, att)); } return res; } /// /// 返回带有Attribute的方法元祖列表 /// /// /// /// public static List GetAll_MethodAndAtt(Type type) where Att : Attribute, new() { var res = new List(); var typeLists = GetAllMethods(type); foreach (var item in typeLists) { var att = GetAttribute(item); res.Add((item, att)); } return res; } }}5.特性应用
5.1 添加说明信息并获取
/// /// 备注特性/// public class RemarkAttribute : Attribute{ private string Remark { get; set; } public RemarkAttribute(string Remark) { this.Remark = Remark; } public string GetRemark() { return this.Remark; }}// 枚举public enum ESex{ [Remark("男")] male = 1, [Remark("女")] female = 2,}/// /// Enum扩展方法/// public static class EnumExtension{ public static string GetRemark(this Enum model) { if (model is ESex) { Type type = typeof(ESex); FieldInfo fi = type.GetField(model.ToString()); object[] attributes = fi.GetCustomAttributes(true); foreach (var attr in attributes) { if (attr is RemarkAttribute) { RemarkAttribute remark = (RemarkAttribute)attr; return remark.GetRemark(); } } } return string.Empty; }}使用:
Console.WriteLine(ESex.male.GetRemark());// 男
5.2 数据验证
可参考:
https://www.cnblogs.com/jiangxifanzhouyudu/p/11107734.html
(1)基类抽象特性
using System;namespace MyAttribute.ValidateExtend{ public abstract class AbstractValidateAttribute : Attribute { public abstract bool Validate(object oValue); }}(2)子类特性实现–数字长度
using System;namespace MyAttribute.ValidateExtend{ [AttributeUsage(AttributeTargets.Property)] public class LongAttribute : AbstractValidateAttribute { private long _Min = 0; private long _Max = 0; public LongAttribute(long min, long max) { this._Min = min; this._Max = max; } public override bool Validate(object oValue) { return oValue != null && long.TryParse(oValue.ToString(), out long lValue) && lValue >= this._Min && lValue public class RequiredAttribute : AbstractValidateAttribute { public override bool Validate(object oValue) { return oValue != null && !string.IsNullOrWhiteSpace(oValue.ToString()); } }} [AttributeUsage(AttributeTargets.Property)] public class StringLengthAttribute : AbstractValidateAttribute { private int _Min = 0; private int _Max = 0; public StringLengthAttribute(int min, int max) { this._Min = min; this._Max = max; } public override bool Validate(object oValue) { return oValue != null && oValue.ToString().Length = this._Min && oValue.ToString().Length public static class AttributeExtend { public static bool Validate Type type = t.GetType(); foreach (var prop in type.GetProperties()) { if (prop.IsDefined(typeof(AbstractValidateAttribute), true)) { object oValue = prop.GetValue(t); foreach (AbstractValidateAttribute attribute in prop.GetCustomAttributes(typeof(AbstractValidateAttribute), true)) { if (!attribute.Validate(oValue)) return false; } } } return true; } }} public static class AttributeExtend { public static bool Validate Type type = t.GetType(); foreach (var prop in type.GetProperties()) { if (prop.IsDefined(typeof(AbstractValidateAttribute), true)) { object oValue = prop.GetValue(t); foreach (AbstractValidateAttribute attribute in prop.GetCustomAttributes(typeof(AbstractValidateAttribute), true)) { if (!attribute.Validate(oValue)) return false; } } } return tue; } }} /// static void Main(string[] args) { try { #region 特性实现数据验证,并且可扩展 { //通过特性去提供额外行为 //数据验证--到处都需要验证 StudentVip student = new StudentVip() { Id = 123, Name = "无为", QQ = 729220650, Salary = 1010000 }; if (student.Validate()) { Console.WriteLine("特性校验成功"); } //1 可以校验多个属性 //2 支持多重校验 //3 支持规则的随意扩展 } #endregion } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.Read(); } }}
- 参数 conditionalSymbol 表示指定的预处理标识符。
上一篇:云服务器怎么选地域?
下一篇:恐龙斑马英语怎么读音?