[C#] C# 知识回顾 – 特性 Attribute

C# 知识回顾 – 特性 Attribute

【博主】反骨仔    【原文地址】http://www.cnblogs.com/liqingwen/p/5911289.html

目录

 

一、特性简介

  特性提供功用强大的不二法门,用以将元数据或声称音信与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,可在运转时采纳“反射”查询特性。

  特性具有以下属性:

    (1)特性可向程序中添韩元数据。元数据是有关在先后中定义的类其余音讯。所有的
.NET
程序集都饱含指定的一组元数据,这个元数据描述在先后集中定义的门类和种类成员。可以添加自定义特性,以指定所需的任何附加信息。

    (2)可以将一个或两个特性应用到全部程序集、模块或较小的先后元素(如类和总体性)。

    (3)特性可以与办法和特性相同的情势接受参数。

    (4)程序可以应用反射检查自己的元数据或其他程序内的元数据。

 

二、使用特性

  特性可以放置在几乎拥有的宣示中(但一定的特征可能限制在其上有效的阐明类型)。在
C#
中,特性的指定方法为:将括在方括号中的特性名置于其应用到的实业的扬言上方。它必须放在所使用于的因素的紧前边并与该因素在同一行。

 1     [Serializable]  //使用特性 SerializableAttribute
 2     internal class MyClass
 3     {
 4         [DllImport("user32.dll")]   //使用特性 DllImportAttribute
 5         private static extern void Do();
 6 
 7         #region 一个声明上可放置多个特性
 8 
 9         private void MethodA([In][Out]ref double n) { }
10         private void MethodB([In, Out]ref double n) { }
11 
12         #endregion 一个声明上可放置多个特性
13 
14         #region 某些特性对于给定实体可以指定多次
15 
16         [Conditional("DEBUG"), Conditional("TEST1")]
17         private void TraceMethod() { }
18 
19         #endregion 某些特性对于给定实体可以指定多次
20     }

  【注意】按照约定,所有特性名称皆以单词“Attribute”截止,以便将它们与“.NET
Framework”中的其他项界别。不过,在代码中选取特性时,不需要指定 attribute
后缀。

 

C#,三、特性的参数

  许多特色都有参数,而这么些参数可以是原则性参数、未命名参数或命名参数。任何固定参数都无法不按一定顺序点名并且不可以简单,而命名参数是可选的且可以按擅自顺序点名。首先指定定位参数。例如,这五个特色是同一的:

1 [DllImport("user32.dll")] 
2 [DllImport("user32.dll", SetLastError=false, ExactSpelling=false)] 

  第一个参数(DLL
名称)是定点参数并且连接第一个冒出,其他参数为命名参数。在这种景色下,六个命名参数均默认为
false,因而可将其简单。

 

四、特性的目的

  特性的靶子是利用该特性的实体。例如,特性能够接纳于类、特定措施或任何程序集。默认境况下,特性应用于它背后的元素。不过,您也足以显式标识要将特色应用于方法或者它的参数或重回值。

  若要显式标识特性目的,语法:

[target : attribute-list]

 

特性目标
C# 适用对象
assembly 整个程序集
module 当前程序集模块
field 在类或结构中的字段
event event
method 方法或 get 和 set 属性访问器
param 方法参数或 set 属性访问器参数
property 属性
return 方法、属性索引器或 get 属性访问器的返回值
type 结构、类、接口、枚举或委托

 

//示例:将特性应用于程序集和模块
[assembly: AssemblyTitle("assembly 4.6.1")]
[module: CLSCompliant(true)]

 1 //示例:将特性应用于方法、方法参数和方法返回值
 2 
 3 //默认:应用于方法
 4 [SomeAttr] 
 5 int Method1() { return 0; } 
 6 
 7 //指定应用于方法
 8 [method: SomeAttr]
 9 int Method2() { return 0; } 
10 
11 //指定应用于返回值
12 [return: SomeAttr] 
13 int Method3() { return 0; }

 

五、特性的广泛用途

  以下列表包含特性的多少个广大用途:

    (1)在 Web
服务中,使用 WebMethod 特性来标记方法,以指示该措施应该可由此 SOAP
协议进行调用。

    (2)描述当与本机代码举办相互操作时咋样封送方法参数。有关更多音信。

    (3)描述类、方法和接口的 COM 属性。

    (4)使用 DllImportAttribute 类调用非托管代码。

    (5)在题目、版本、表明或商标方面描述您的次第集。

    (6)描述要持久性系列化类的如何成员。

    (7)描述咋样映射类成员和 XML 节点以便举办 XML 连串化。

    (8)描述方法的双鸭山要求。

    (9)指定用于强制安全性的性状。

    (10)由实时 (JIT) 编译器控制优化,以便易于调试代码。

    (11)获取有关调用方的信息的措施。

 

六、创造自定义的性状

   通过定义一个特性类,可以成立您自己的自定义特性。该特性类直接或直接地从 Attribute 派生,有助于方便连忙地在元数据中标识特性定义。

 1     /// <summary>
 2     /// 角色特性
 3     /// </summary>
 4     /// RoleAttribute:特性的名称,继承 Attribute,为自定义特性
 5     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
 6     public class RoleAttribute : Attribute
 7     {
 8         private string _name;
 9 
10         /// <summary>
11         /// 启用标识
12         /// </summary>
13         /// IsEnable:命名参数
14         public bool IsEnable { get; set; }
15 
16         /// <summary>
17         /// 构造函数
18         /// </summary>
19         /// <param name="name"></param>
20         /// name:定位参数
21         public RoleAttribute(string name)
22         {
23             _name = name;
24         }
25     }

1     [Role("Me", IsEnable = true)]   //调用特性的方式
2     public class OurClass
3     {
4 
5     }

  构造函数的参数是自定义特性的定点参数,任何集体的读写字段或性质都是命名参数。【注意】 AttributeUsage 特性,在这里它使得 Role
特性仅在类和 struct 宣示中有效。

 

1     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]  //AllowMultiple:该值指示能否为一个程序多次使用该特性
2     public class RoleAttribute : Attribute
3     {
4         //... ...
5     }

1     [Role("You")]            //在同一个类上多次使用
2     [Role("Me", IsEnable = true)]   
3     public class OurClass
4     {
5         //... ...
6     }

  【注意】如若特性类富含一个性质,则该属性必须为读写属性。

 

七、使用反射访问特性

   使用反射,可寻找用自定义特性定义的信息。紧要措施是 GetCustomAttributes,它回到对象数组,这么些目的在运行时等效于源代码特性。

C# 1C# 2

 1     /// <summary>
 2     /// 角色特性
 3     /// </summary>
 4     /// RoleAttribute:特性的名称,继承 Attribute,为自定义特性
 5     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
 6     public class RoleAttribute : Attribute
 7     {
 8         private string _name;
 9         /// <summary>
10         /// 启用标识
11         /// </summary>
12         public bool IsEnable { get; set; }
13 
14         /// <summary>
15         /// 构造函数
16         /// </summary>
17         /// <param name="name"></param>
18         public RoleAttribute(string name)
19         {
20             _name = name;
21         }
22     }

RoleAttribute.cs

1     [Role("Me", IsEnable = true)]   
2     public class OurClass
3     {
4         //... ...
5     }

  概念上等效于

1     RoleAttribute role = new RoleAttribute("Me");
2     role.IsEnable = true;

  不过,直到询问 OurClass 来博取特性后才会举办此代码。对 OurClass 调用 GetCustomAttributes 会导致按上述模式协会并开端化一个 RoleAttribute 对象。假诺此类具有其他特色,则按一般的艺术社团其他特色对象。然后 GetCustomAttributes 重回 RoleAttribute 对象和数组中的任何其余特色对象。之后就足以对此数组举行迭代,确定按照各类数组元素的门类所采纳的特性,并从特性对象中领到消息。

   这里,定义一个自定义特性,将其选择于若干实体并因此反射举行搜索。

 1     /// <summary>
 2     /// 角色特性
 3     /// </summary>
 4     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
 5     public class RoleAttribute : Attribute
 6     {
 7         private readonly string _name;
 8 
 9         /// <summary>
10         /// 启用标识
11         /// </summary>
12         public bool IsEnable { get; set; }
13 
14         /// <summary>
15         /// 构造函数
16         /// </summary>
17         /// <param name="name"></param>
18         public RoleAttribute(string name)
19         {
20             _name = name;
21         }
22 
23         public string GetName()
24         {
25             return _name;
26         }
27     }

    class MyClass1 { }

    [Role("Me")]
    class MyClass2 { }

    [Role("Me"), Role("You", IsEnable = true)]
    class MyClass3 { }

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Output(typeof(MyClass1));
 6             Output(typeof(MyClass2));
 7             Output(typeof(MyClass3));
 8 
 9             Console.Read();
10         }
11 
12         /// <summary>
13         /// 输出
14         /// </summary>
15         /// <param name="t"></param>
16         static void Output(Type t)
17         {
18             Console.WriteLine($"Class: {t}");
19 
20             var attributes = t.GetCustomAttributes();
21             foreach (var attribute in attributes)
22             {
23                 var attr = attribute as RoleAttribute;
24 
25                 if (attr == null)
26                 {
27                     return;
28                 }
29 
30                 Console.WriteLine($"    Name: {attr.GetName()}, IsEnable: {attr.IsEnable}");
31             }
32         }
33     }

C# 3

 

 

 

 

 

 

传送门

  《只是想大概说下表达式树 – Expression
Trees

  《只是想大概说下体系化

 


【参考】微软官方文档

相关文章