特性(attribute)是被指定给某一声明的一则附加的声明性信息。
在C#中,有一个小的预定义特性集合。在学习如何建立我们自己的定制特性(custom attributes)之前,我们先来看看在我们的代码中如何使用预定义特性。
using System;
public class AnyClass
{
[Obsolete("Don't use Old method, use New method", true)]
static void Old( ) { }
static void New( ) { }
public static void Main( )
{
Old( );
}
}
我们先来看一下上面这个例子,在这个例子中我们使用了Obsolete特性,它标记了一个不应该再被使用的程序实体。第一个参
数是一个字符串,它解释了为什么该实体是过时的以及应该用什么实体来代替它。实际上,你可以在这里写任何文本。第二个参数告诉编译器应该把使用这个过时的
程序实体当作一种错误。它的默认值是false,也就是说编译器对此会产生一个警告。
当我们尝试编译上面这段程序的时候,我们将会得到一个错误:
AnyClass.Old()' is obsolete: 'Don't use Old method, use New method'
开发定制特性(custom attributes)
现在让我们来看看如何开发我们自己的特性。
首先我们要从System.Attribute派生出我们自己的特性类(一个从System.Attribute抽象类继承而来的类,不管是直接还是间接继承,都会成为一个特性类。特性类的声明定义了一种可以被放置在声明之上新的特性)。
using System;
public class HelpAttribute : Attribute
{
}
不管你是否相信,我们已经建立了一个定制特性,现在我们可以用它来装饰现有的类就好像上面我们使用Obsolete attribute一样。
[Help()]
public class AnyClass
{
}
注意:对一个特性类名使用Attribute后缀是一个惯例。然而,当我们把特性添加到一个程序实体,是否包括
Attribute后缀是我们的自由。编译器会首先在System.Attribute的派生类中查找被添加的特性类。如果没有找到,那么编译器会添加
Attribute后缀继续查找。
到目前为止,这个特性还没有起到什么作用。下面我们来添加些东西给它使它更有用些。
using System;
public class HelpAttribute : Attribute
{
public HelpAttribute(String Descrition_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
[Help("this is a do-nothing class")]
public class AnyClass
{
}
在上面的例子中,我们给HelpAttribute特性类添加了一个属性并且在后续的部分中我们会在运行时环境中查寻它。
定义或控制特性的使用
AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如和被使用。
AttributeUsage有三个属性,我们可以把它放置在定制属性前面。第一个属性是:
ValidOn
通过这个属性,我们能够定义定制特性应该在何种程序实体前放置。一个属性可以被放置的所有程序实体在AttributeTargets enumerator中列出。通过OR操作我们可以把若干个AttributeTargets值组合起来。
AllowMultiple
这个属性标记了我们的定制特性能否被重复放置在同一个程序实体前多次。
Inherited
我们可以使用这个属性来控制定制特性的继承规则。它标记了我们的特性能否被继承。
下面让我们来做一些实际的东西。我们将会在刚才的Help特性前放置AttributeUsage特性以期待在它的帮助下控制Help特性的使用。
using System;
[AttributeUsage(AttributeTargets.Class), AllowMultiple = false,
Inherited = false ]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
先让我们来看一下AttributeTargets.Class。它规定了Help特性只能被放在class的前面。这也就意味着下面的代码将会产生错误:
[Help("this is a do-nothing class")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
编译器报告错误如下:
AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
It is valid on 'class' declarations only.
我们可以使用AttributeTargets.All来允许Help特性被放置在任何程序实体前。可能的值是:
Assembly,Module,Class,Struct,Enum,Constructor,Method,Property,Field,Event,Interface,
Parameter,Delegate。
All = Assembly | Module | Class | Struct | Enum | Constructor | Method
| Property | Field | Event | Interface | Parameter | Delegate,
ClassMembers = Class | Struct | Enum | Constructor | Method | Property | Field | Event | Delegate | Interface )
下面考虑一下AllowMultiple = false。它规定了特性不能被重复放置多次。
[Help("this is a do-nothing class")]
[Help("it contains a do-nothing method")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
它产生了一个编译期错误。
AnyClass.cs: Duplicate 'Help' attribute
Ok,现在我们来讨论一下最后的这个属性。Inherited, 表明当特性被放置在一个基类上时,它能否被派生类所继承。
[Help("BaseClass")]
public class Base
{
}
public class Derive : Base
{
}
这里会有四种可能的组合:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]
第一种情况:
如果我们查询(Query)(稍后我们会看到如何在运行期查询一个类的特性)Derive类,我们将会发现Help特性并不存在,因为inherited属性被设置为false。
第二种情况:
和第一种情况相同,因为inherited也被设置为false。
第三种情况:
为了解释第三种和第四种情况,我们先来给派生类添加点代码:
[Help("BaseClass")]
public class Base
{
}
[Help("DeriveClass")]
public class Derive : Base
{
}
现在我们来查询一下Help特性,我们只能得到派生类的属性,因为inherited被设置为true,但是AllowMultiple却被设置为false。因此基类的Help特性被派生类Help特性覆盖了。
第四种情况:
在这里,我们将会发现派生类既有基类的Help特性,也有自己的Help特性,因为AllowMultiple被设置为true。
定义或控制特性的使用
AttributeUsage类是另外一个预定义特性类,它帮助我们控制我们自己的定制特性的使用。它描述了一个定制特性如和被使用。
分享到:
相关推荐
在标题“C#特性Attribute的实际应用之:为应用程序提供多个版本”中,我们可以看到一个具体的应用场景,即利用特性来区分和管理应用程序的不同版本,如体验版和完整功能版。 首先,我们来看如何创建自定义特性。在...
【内容概要】:在C#中通过学习使用Attribute,实现一个简单的ORM框架。里面主要有两部分的内容,学习使用Attribute获得设定值;学习通过反射获取属性的值 【适应人群】:初级工程师。但需要对反射、Attribute有一定...
标签中的"C#"表明我们讨论的是.NET框架中的C#语言,"attribute"对应上面提到的特性,"aop"则是本文的核心——面向切面编程。在实际项目中,利用Attribute实现AOP可以帮助我们编写更加整洁、可维护的代码,同时减少...
【内容概要】:在C#中使用反射获得Attribute(特性)的设定值。 【涉及的知识点】:自定义Attribute、C#中的反射知识 【使用人群】:初级工程师,适合刚开始学习的人群 【使用场景及目标】:学习如何使用反射获取...
在.NET框架中,C#语言提供了强大的特性(Attribute)机制,这是一种元数据,可以附加到...这份"Visual Studio2017c#中的特性(attribute)+反射源码大全"资源应该包含了多个示例和实践,帮助学习者掌握这两个核心概念。
} = "欢迎使用C#特性!"; } ``` XAML部分: ```xml xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> ``` 在这个WPF应用中...
本文主要给大家介绍了关于C#基础之Attribute和反射的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 Attribute(特性) Attribute是C#的一种语言特性,用于为各种实体(class,field,...
本项目通过引入Attribute特性,旨在简化Unity框架的IOC注入过程,使代码更加简洁易读。Attribute在.NET中是一种元数据,可以附加到程序元素(如类、方法、属性等)上,提供额外的信息,通常用于运行时反射和自定义...
特性(Attribute)是C#的一种用于声明性编程的机制,允许开发者在代码中添加元数据。通过特性,我们可以为方法、类、字段等添加额外的信息,这些信息可以在运行时通过反射来读取和使用。 ### 编译器*** *** ...
20. AOP(面向切面编程):利用特性(Attribute)实现代码的解耦,例如日志记录、性能监控等。 以上内容是“C#分等级学习”的核心要点,通过系统学习和实践,无论是初学者还是有一定基础的开发者,都能在C#的世界里...
总的来说,这个项目演示了如何在C#中创建自定义特性,以及如何通过反射获取和使用这些特性中的数据,是学习C#元编程和反射机制的一个实用案例。通过深入理解这部分内容,开发者可以更好地实现代码的自我描述,提高...
同时,C#也引入了特性(attribute),允许向元数据添加信息,对代码进行标记和自定义。 最后,C#还支持单元测试和代码调试,这对于软件质量保证至关重要。利用Visual Studio或其他IDE提供的工具,开发者可以编写...
下面我们将深入探讨C#特性的概念、类型以及如何在实际项目中使用它们。 一、特性基础 1. 特性的定义:C#的特性以`[ ]`包围,以关键字`Attribute`作为基类,如`[Serializable]`表示对象可以序列化。自定义特性则...
11. **特性(Attribute)**:C#的特性允许在代码中添加元数据,这些元数据可以被编译器或运行时环境使用。 以上只是C#众多知识点的一部分,实际的PPT教程可能会深入到每个主题,并给出示例代码和解释,帮助学习者...
### 博客园C#文章精华知识点概览 #### 一、C#基础知识与特性 1. **C#和.NET中的类型转换** - **基础知识**:了解C#中的基本数据类型及其转换规则。...这对于想要深入学习C#的开发者来说是一份宝贵的资源。
其中还包括了关于使用特性(Attribute)来增强代码功能的指导,这是C#语言特有的强大特性之一。 .NET Compiler Platform SDK(也称为Roslyn API)的部分为那些希望深入编译器工作原理的读者提供了入门知识。这份...
C#支持特性(Attribute),可以定义自定义特性来表示切面,并在运行时通过反射找到并执行这些特性。这种方式简单易用,但可能会导致代码可读性下降,且需要在运行时解析特性,性能上可能不如前两者。 4. **拦截器...
9. **特性(Attribute)**:特性提供了一种元数据的方式,可以为代码添加附加信息,如.NET框架中的Serializable、DllImport等。 10. **.NET框架和库**:C#是.NET框架的一部分,使用.NET库(如System, System....
5. AOP(面向切面编程)和装饰器:C#通过特性(Attribute)支持元编程和部分AOP思想,书籍会探讨如何利用特性进行代码注解和实现行为注入,以提高代码的灵活性和可维护性。 6. 异步编程:随着异步I/O和async/await...
《入门c#指南.pdf》是一份详尽的C#编程语言学习资源,由Microsoft官方提供,覆盖了C#编程语言的各个方面,包括基础概念、编程指南、最新版本的新特性以及丰富的编程示例。该指南适合新手和有经验的开发者,为他们...