【C#语法】类和方法的特性Attribute
2017-07-03 20:28
381 查看
一、引言
今天,我们来聊一下C#中的特性Attribute。何为特性Attribute?我们先看一个特性的使用例子,我们定义了一个Human类,但是由于某种原因该类不再被使用,但是我又不想将该类的代码注释或者删除掉,于是我们就可以通过给它赋予Obsolete特性来禁止别人使用:[Obsolete("该类已经过时,不能再使用",true)] public class Human { public string Name { get; set; } public Human Child { get; set; } }当我们在代码中使用该类时,发现编译器会报错,并提示我们自定义的提示信息。
这是在main函数中使用Human类:
class Program { static void Main(string[] args) { Human human; } }这是编译器报的错误:
我们在Human类前面添加的obsolete就是该类的一个特性,与之相对,我们接触最多的应该是类的属性Property,Human类的Name和Child就是其两个属性。特性本质就是一个类,Obsolete中传递的两个参数就是该类的构造函数所需的参数,第一个是在编译出错时编译器要提示的字符串,第二个是指是否
报错,如果为true编译时就会报错。特性除了可以放到类前面之外,也可以放到方法和属性的前面。
二、特性属于类而非属于对象
在很多的资料中,都把特性比作类在某一特性环境下的属性。比如对于Human类,把一个人放到学校中它就有年级等特性,把它放到公司中就有部门等特性,这种特性不是它与生既来的(与生既来的是属性Proerty),而是随着环境的不同而发生变化。虽然这种解释很形象,但是很容易让人发生误解——某一个对象具有特性!而实际上,特性是属于类而非一个对象,这点类似于类的静态成员,我们不能通过一个human实例获取Human类的特性,只能通过诸如以下的语句来获取其特性:object[] attributes = typeof(Human).GetCustomAttributes(true);其实,要想理解这个问题。我们需要了解特性的用途:特性不是给程序员用的,而是给编译器看的。它告诉编译器这个类具有何特性,在何种情况下应该作何处理!比如在上面的类型中,告诉编译器该类已经不能被使用了;再比如我们在类前面添加
[Serializable]特性,告诉编译器,该类支持序列化。
三、自定义特性
在前面的例子中,我们提到过,特性的本质其实就是一个类,这个类必须继承自Attribute基类,而且类名一般要求格式为“名称+Attribute”的形式。我们现在为Human类定义一个Help的属性,来告诉使用者Human类的信息:public class HelpAttribute : Attribute { public Help(string info) { this.Info = info; } public string Info { get; private set; } }我们在使用时可以加Attribute或者不加Attribute,如下面的格式:
[Help("这是一个Human类")]
或者
[HelpAttribute("这是一个Human类")]
因为编译器在处理特性时会先查找特性名称,如果找不到就自动加上Attribute再次进行查找。
我们在主函数中查找类的特性并输出:
static void Main(string[] args) { object[] attributes = typeof(Human).GetCustomAttributes(true); HelpAttribute attribute=attributes[0] as HelpAttribute; Console.WriteLine(attribute.Info); }得到的结果如下:
四、使用转换类TypeConvertAttribute
接下来,定义一个用于进行类型转换的类,我们将字符串转换成human类对象:public class StringToHumanConverter : TypeConverter { public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { if (value is String) { Human h = new Human(); h.Name = value as String; return h; } return base.ConvertFrom(context, culture, value); } }接下来,将特性赋予Human类 :
[TypeConverterAttribute(typeof(StringToHumanConverter))] public class Human { public string Name { get; set; } public Human Child { get; set; } }
我们定义的这个类,不能在cs代码中直接用来将字符串和Human类对象的隐式转换,诸如下面的用法是错误的:
Human human = str as Human;我们想在cs代码中进行转换,只能定义一个StringToHumanConverter对象,调用其ConverFrom方法进行转换:
String str = "hyman"; StringToHumanConverter convert = new StringToHumanConverter(); Human human = (Human)convert.ConvertFrom(str);
但是这种转换可以在XMAL中直接使用:
<Window.Resources>
<local:Human x:Key="human" Child="tom"/>
</Window.Resources> 我们在后台代码中可以通过FindResource找到该资源,发现已经可以正常打印出其Child的Name,这是因为WPF的框架自动调用TypeConverter进行了转换:
private void button1_Click(object sender, RoutedEventArgs e)
{
Human human = (Human)this.FindResource("human");
MessageBox.Show(human.Child.Name);
}
相关文章推荐
- .NET(C#):获取方法返回值的自定义特性(Attribute)
- C#提高--------------获取方法返回值的自定义特性(Attribute)
- 怎样在前端Javascript中调用C#方法(3)使用特性Attribute
- [C#]Attribute特性(2)——方法的特性及特性参数
- [导入]C# 特性(Attribute)入门
- C# 特性(Attribute)(一)
- C# 特性(Attribute)入门
- C#2.0新的语法扩充(泛型,迭代器,匿名方法)
- C# 3.0语言新特性(语言规范):2 扩展方法
- C# 3.0新特性之扩展方法
- C#中的特性Attribute
- C# 特性(Attribute)入门
- C# 3.0/3.5语法新特性示例汇总
- 步步为营VS 2008 + .NET 3.5(4) - C# 3.0新特性之LambdaExpressions(Lambda表达式)、QuerySyntax(查询语法)和AnonymousTypes(匿名类型)
- C#2.0中主要的语法新特性
- C# 特性(Attribute)(二)
- C# 特性(Attribute)入门
- C# 特性(Attribute)入门教程
- c#2.0新特性:(二)匿名方法(Anonymous Methods)
- 步步为营VS 2008 + .NET 3.5(3) - C# 3.0新特性之Automatic Properties(自动属性)、Object Initializers(对象初始化器)、Collection Initializers(集合初始化器)和Extension Methods(扩展方法)