小工具知识网

当前位置: 首页 > 行业知识 > C# 特性(Attribute)超详细教程

行业知识

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 属性访问器参数
              propertyProperty(属性)
              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();        }    }}

上一篇:云服务器怎么选地域?

下一篇:恐龙斑马英语怎么读音?