【问题标题】:C# Attributes and their usesC# 属性及其用途
【发布时间】:2010-07-07 17:24:45
【问题描述】:

我真的不太了解 C# 中的一般属性,我已经看到它们以许多不同的方式/地方使用,但我认为我没有看到其中一些的重要性。有些肯定很重要,因为它们提供了明显的功能,例如[Serializable]。然而,其他的似乎并不那么重要,比如我的同事用[DataMember] 标记属性。

我想我的问题是,什么是属性,它们有什么用处?有没有办法创建我自己的属性,我如何判断字段/方法/类/是否具有特定属性或在这些属性中设置了哪些值?

【问题讨论】:

标签: c# attributes


【解决方案1】:

什么是属性?

属性使您能够在描述该类型或方法的元数据中嵌入有关类型或方法的信息。

You typically want to use attributes to describe facts about the mechanism of the type or method rather than the meaning of the type or method. 例如,假设您有一个 Employee 类型。关于Employee 的含义的一个事实是它是一种Person,一个Employee 有一个Manager,等等。关于 Employee 的机制 的一个事实是,它可以是数据绑定的目标,也可以序列化到磁盘,或其他任何东西。一个员工不能被序列化到磁盘,但class Employee 可以。属性让您可以将有关技术细节的信息与语义模型分开。

有没有办法创建我自己的属性?

是的。创建一个扩展属性的类。按照惯例,您希望将其命名为“FooAttribute”。如果这样做,您可以自行决定使用 [Foo] 语法或 [FooAttribute] 语法。

我如何判断字段/方法/类/任何东西是否具有特定属性或在这些属性中设置了哪些值?

对反射对象使用 GetCustomAttributes 方法。

我应该在哪里阅读以获取更多信息?

从属性教程开始:

http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

然后阅读 C# 规范第 17 章的全部内容。

【讨论】:

    【解决方案2】:

    Attributes 是一种将元数据与 .NET 中的类型相关联的方法。这允许您检查类型并获取与类型的“运行时”信息分开的有关它的信息。

    这可能非常有用。您提到了[Serializable],但其他简单示例包括许多System.ComponentModel 类型,例如Description,当您在设计器中使用它们时,属性网格使用它来“描述”属性。由于属性的“描述”与程序中类型的行为(在运行时)并不真正相关,因此它不属于类。但是,当您在可视化设计器中编辑控件时,它非常方便,例如,查看属性的描述(或类别等)。属性是处理这种情况的方法。

    【讨论】:

    • 您可以通过从 System.Attribute 类继承来创建自己的属性,并指定它的范围以查询用您可以使用反射的属性装饰的类/方法 foreach (var attrib in typeof(YOURCLASS) .GetCustomAttributes())
    【解决方案3】:

    我认为以下问题的答案将为您提供一些关于您的问题的见解。

    How do attribute classes work?

    这是我提供的答案的转贴。

    属性本质上是元数据,可以附加到代码的各个部分。然后可以查询此元数据并影响某些操作的行为。

    属性几乎可以应用于代码的每个方面。例如,属性可以在程序集级别关联,如 AssemblyVersion 和 AssemblyFileVersion 属性,它们控制与程序集关联的版本号。

    [assembly: AssemblyVersion("1.0.0.0")]
    [assembly: AssemblyFileVersion("1.0.0.0")]
    

    然后,例如可以将 Serializable 属性应用于类型声明,以将类型标记为支持序列化。事实上,这个属性在 CLR 中具有特殊含义,实际上作为特殊指令直接存储在 IL 中的类型上,这经过优化以存储为可以更有效地处理的位标志,有一些属性这种性质,称为伪自定义属性。

    仍然可以将其他属性应用于方法、属性、字段、枚举、返回值等。您可以通过查看此链接了解属性可以应用于的可能目标 http://msdn.microsoft.com/en-us/library/system.attributetargets(VS.90).aspx

    除此之外,您还可以定义自己的自定义属性,然后将这些属性应用于您的属性所针对的适用目标。然后在运行时,您的代码可以反映自定义属性中包含的值并采取适当的措施。

    举一个相当幼稚的例子,这只是为了举例:) 您可能想要编写一个持久性引擎,该引擎将自动将类映射到数据库中的表,并将类的属性映射到表列。您可以从定义两个自定义属性开始

    TableMappingAttribute
    ColumnMappingAttribute
    

    然后你可以将它应用到你的类中,例如我们有一个 Person 类

    [TableMapping("People")]
    public class Person
    {
      [ColumnMapping("fname")]
      public string FirstName {get; set;}
    
      [ColumnMapping("lname")]
      public string LastName {get; set;}
    }
    

    编译时,除了编译器发出由自定义属性定义的附加元数据这一事实外,几乎没有其他影响。但是,您现在可以编写一个 PersistanceManager,它可以动态检查 Person 类实例的属性并将数据插入到 People 表中,将 FirstName 属性中的数据映射到 fname 列,将 LastName 属性映射到 lname 列。

    关于你关于属性实例的问题,属性的实例不是为你的类的每个实例创建的。 People 的所有实例将共享同一 TableMappingAttribute 和 ColumnMappingAttributes 实例。实际上,属性实例只有在您第一次真正查询属性时才会创建。

    【讨论】:

      【解决方案4】:

      C# 提供了一种定义声明性标记(称为属性)的机制,您可以将其放置在源代码中的某些实体上以指定附加信息。属性包含的信息可以在运行时通过反射来检索。您可以使用预定义的属性,也可以定义自己的自定义属性。

      http://msdn.microsoft.com/en-us/library/aa288059%28v=VS.71%29.aspx

      【讨论】:

        猜你喜欢
        • 2013-07-06
        • 2011-06-26
        • 2014-09-09
        • 1970-01-01
        • 2012-08-17
        • 1970-01-01
        • 2011-05-01
        • 2017-09-18
        • 2014-10-17
        相关资源
        最近更新 更多