温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

.NET基础编程之特性 - Attribute

发布时间:2020-06-13 20:37:05 来源:网络 阅读:618 作者:IT大赢家 栏目:编程语言

  这一篇文章是给大家介绍的是:.NET基础编程之特性 - Attribute,对这一部分掌握不熟悉的同学,可以仔细的看一下!

      一、特性简介

  特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集、类型、方法、属性等)相关联。特性与程序实体关联后,可在运行时使用“反射”查询特性。

  特性具有以下属性:

  (1)特性可向程序中添加元数据。元数据是有关在程序中定义的类型的信息。所有的 .NET 程序集都包含指定的一组元数据,这些元数据描述在程序集中定义的类型和类型成员。可以添加自定义特性,以指定所需的任何附加信息。

  (2)可以将一个或多个特性应用到整个程序集、模块或较小的程序元素(如类和属性)。

  (3)特性可以与方法和属性相同的方式接受参数。

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

  二、使用特性

  特性可以放置在几乎所有的声明中(但特定的特性可能限制在其上有效的声明类型)。在 C# 中,特性的指定方法为:将括在方括号中的特性名置于其应用到的实体的声明上方。它必须位于所应用于的元素的紧前面并与该元素在同一行。

  [Serializable] //使用特性 SerializableAttribute

  internal class MyClass

  {

  [DllImport("user32.dll")] //使用特性 DllImportAttribute

  private static extern void Do();

  #region 一个声明上可放置多个特性

  private void MethodA([In][Out]ref double n) { }

  private void MethodB([In, Out]ref double n) { }

  #endregion 一个声明上可放置多个特性

  #region 某些特性对于给定实体可以指定多次

  [Conditional("DEBUG"), Conditional("TEST1")]

  private void TraceMethod() { }

  #endregion 某些特性对于给定实体可以指定多次

  }

  【注意】根据约定,所有特性名称都以单词“Attribute”结束,以便将它们与“.NET Framework”中的其他项区分。但是,在代码中使用特性时,不需要指定 attribute 后缀。

  三、特性的参数

  许多特性都有参数,而这些参数可以是定位参数、未命名参数或命名参数。任何定位参数都必须按特定顺序指定并且不能省略,而命名参数是可选的且可以按任意顺序指定。首先指定定位参数。例如,这三个特性是等效的:

  [DllImport("user32.dll")]

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

  第一个参数(DLL 名称)是定位参数并且总是第一个出现,其他参数为命名参数。在这种情况下,两个命名参数均默认为 false,因此可将其省略。

  四、特性的目标

  特性的目标是应用该特性的实体。例如,特性可以应用于类、特定方法或整个程序集。默认情况下,特性应用于它后面的元素。但是,您也可以显式标识要将特性应用于方法还是它的参数或返回值。

  若

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

  [target : attribute-list]

  .NET基础编程之特性 - Attribute

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

  [module: CLSCompliant(true)]

  //示例:将特性应用于方法、方法参数和方法返回值

  //默认:应用于方法

  [SomeAttr]

  int Method1() { return 0; }

  //指定应用于方法

  [method: SomeAttr]

  int Method2() { return 0; }

  //指定应用于返回值

  [return: SomeAttr]

  int Method3() { return 0; }

  五、特性的常见用途

  以下列表包含特性的几个常见用途:

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

  (2)描述当与本机代码进行交互操作时如何封送方法参数。有关更多信息。

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

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

  (5)在标题、版本、说明或商标方面描述您的程序集。

  (6)描述要持久性序列化类的哪些成员。

  (7)描述如何映射类成员和 XML 节点以便进行 XML 序列化。

  (8)描述方法的安全要求。

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

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

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

  六、创建自定义的特性

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

  ///

  /// 角色特性

  ///

  /// RoleAttribute:特性的名称,继承 Attribute,为自定义特性

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]

  public class RoleAttribute : Attribute

  {

  private string _name;

  ///

  /// 启用标识

  ///

  /// IsEnable:命名参数

  public bool IsEnable { get; set; }

  ///

  /// 构造函数

  ///

  ///

  /// name:定位参数

  public RoleAttribute(string name)

  {

  _name = name;

  }

  }

  [Role("Me", IsEnable = true)] //调用特性的方式

  public class OurClass

  {

  }

  构造函数的参数是自定义特性的定位参数,任何公共的读写字段或属性都是命名参数。

  【注意】 AttributeUsage 特性,在这里它使得 Role 特性仅在类和 struct 声明中有效。

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]  //AllowMultiple:该值指示能否为一个程序多次使用该特性

  public class RoleAttribute : Attribute

  {

  //... ...

  }

  [Role("You")]            //在同一个类上多次使用

  [Role("Me", IsEnable = true)]

  public class OurClass

  {

  //... ...

  }

  注意:如果特性类包含一个属性,则该属性必须为读写属性。

  七、使用反射访问特性

  使用反射,可检索用自定义特性定义的信息。

  主要方法是GetCustomAttributes,它返回对象数组,这些对象在运行时等效于源代码特性。

  ///

  /// 角色特性

  ///

  /// RoleAttribute:特性的名称,继承 Attribute,为自定义特性

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]

  public class RoleAttribute : Attribute

  {

  private string _name;

  ///

  /// 启用标识

  ///

  public bool IsEnable { get; set; }

  ///

  /// 构造函数

  ///

  ///

  public RoleAttribute(string name)

  {

  _name = name;

  }

  }

  RoleAttribute.cs

  [Role("Me", IsEnable = true)]

  public class OurClass

  {

  //... ...

  }

  概念上等效于

  RoleAttribute role = new RoleAttribute("Me");

  role.IsEnable = true;

  但是,直到查询 OurClass 来获取特性后才会执行此代码。对 OurClass 调用 GetCustomAttributes 会导致按上述方式构造并初始化一个 RoleAttribute 对象。如果该类具有其他特性,则按相似的方式构造其他特性对象。

  然后 GetCustomAttributes 返回 RoleAttribute 对象和数组中的任何其他特性对象。之后就可以对此数组进行迭代,确定根据每个数组元素的类型所应用的特性,并从特性对象中提取信息。

  这里,定义一个自定义特性,将其应用于若干实体并通过反射进行检索。

  ///

  /// 角色特性

  ///

  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]

  public class RoleAttribute : Attribute

  {

  private readonly string _name;

  ///

  /// 启用标识

  ///

  public bool IsEnable { get; set; }

  ///

  /// 构造函数

  ///

  ///

  public RoleAttribute(string name)

  {

  _name = name;

  }

  public string GetName()

  {

  return _name;

  }

  }

  class MyClass1 { }

  [Role("Me")]

  class MyClass2 { }

  [Role("Me"), Role("You", IsEnable = true)]

  class MyClass3 { }

  class Program

  {

  static void Main(string[] args)

  {

  Output(typeof(MyClass1));

  Output(typeof(MyClass2));

  Output(typeof(MyClass3));

  Console.Read();

  }

  ///

  /// 输出

  ///

  ///

  static void Output(Type t)

  {

  Console.WriteLine($"Class: {t}");

  var attributes = t.GetCustomAttributes();

  foreach (var attribute in attributes)

  {

  var attr = attribute as RoleAttribute;

  if (attr == null)

  {

  return;

  }

  Console.WriteLine($" Name: {attr.GetName()}, IsEnable: {attr.IsEnable}");

  }

  }

  }

  .NET基础编程之特性 - Attribute


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI