写点什么

C#中的属性

作者:喵叔
  • 2021 年 12 月 21 日
  • 本文字数:1932 字

    阅读完需:约 6 分钟

@TOC这篇文章主要面向的对象是初级开发人员,以及对属性不是很熟悉的开发人员。

什么是属性(Attribute)

属性在 C#中很常用,但有部分开发人员对它既熟悉又陌生。概念上属性是将元数据关联到元素的方式。属性的使用方法我们在代码中经常肩见到,比如下面这样的:


[Test]public class MyClass{   //more code}
复制代码


在上面的样例代码中 Test 就是一个属性。属性是放在类、字段和方法等定义的前面(上面),用来指定特定内容的。.Net 框架中为我们提供了一些常用属性。比如 Serializable,它告诉编译器当前类可以序列化成 JSON 或 XML。


TIP:属性在编译的时候会嵌入到程序集中。我们可以使用反射来获得属性的值。

自定义属性

当.Net 框架提供的属性不足以满足我们开发的要求时,我们可以自定义属性,自定义属性在项目中算比较常用的技术。定义自定义属性需继承抽象类 System.Attribute。比如当创建一个汽车类,需要一个属性来表示汽车的品牌、型号时,我们可以像下面代码这样实现自定义属性:


public class CarAttribute : Attribute{    public string Brand { get; set; }    public string Model { get; set; }
public CarAttribute (string brand, int model) { Brand = brand; Model = model; }}
复制代码


通过上面的代码我们可以看出,属性其实就是一个类,它和其它类一样,也拥有字段、方法、构造函数等成员。

如何使用属性

在本文的前面说过,属性可以放在类、字段和方法等定义的前面(上面),那么,我们来看一下如何使用上一小节中自定义的属性,代码如下:


[Car("BMW", "x3")]public class Carriage{  //more code}
复制代码


在这里这儿需要注,自定义属性的名字,如果我使用的是 xxx+Attribute 的形式来命名名称的话,那么在使用时可以用短名称 xxx(例如上面代码中的 Car 就是使用的是 CarAttribute 的短名称)

限制属性使用范围

属性本身是一个类,因此属性也可以用其他属性来指定和修饰。常用的修饰属性的属性是 AttributeUsage 属性,它用来限制自定义属性可以修饰的元素类型,例如我们将 CarAttribute 属性的使用范围限制为类和接口,可以这么做:


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]public class CarAttribute: Attribute {  //more code}
复制代码


AttributeUsage 属性的参数 AttributeTargets 是一个枚举,包括类、接口、方法、构造函数、枚举、程序集等枚举内容。经过修改后的 CarAttribute 属性只能用在类和接口中,如果用它来修饰字段,编译器就会报错。AttributeUsage 还允许我们定义从修饰对象继承的对象,是否也获得该属性。同样我们将 CarAttribute 修改为从修饰对象继承的对象可以获得该属性:


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = true)]public class CarAttribute: Attribute {  //more code}
复制代码


同时我们也能指定属性是否可以在一个元素上有多个实例,例如下面的代码就定义了 CarAttribute 属性不允许在一个元素上有多个实例:


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]public class CarAttribute: Attribute {  //more code}
复制代码

如何访问属性

到这里一定有小伙伴问,如何访问属性呢?其实.NET 框架为我们提供了 Attribute.GetCustomAttribute()方法来访问属性,简单的用法如下:


var carType = typeof(Carriage);var attributeType = typeof(CarAttribute);var attribute = (CarAttribute)Attribute.GetCustomAttribute(carType , attributeType);Console.WriteLine($"Car is {attribute.Brand} {attribute.Model}");
复制代码


反射访问


除了上面的访问方式外,还有一种常用的访问方式:反射访问。反射的主要的作用是用来收集对象的数据而不是对象本身的数据。这些数据包括对象的类型、对象的成员的信息、特定程序集信息以及存储在元素属性中的任何信息。最简单的反射是 GetType()方法,代码如下:


int myNum= 88;Type type = myNum.GetType();Console.WriteLine(type);
复制代码


我们还可以使用反射来获取关于包含给定类型的程序集的信息:


Assembly mobileAssembly = typeof(Carriage).Assembly;Console.WriteLine(mobileAssembly);
复制代码


反射同样可以获得属性的信息和对象构造函数的信息:


PropertyInfo property = reflected.GetType().GetProperty("PropertyOne");Console.WriteLine(property);ConstructorInfo constructor = reflected.GetType().GetConstructor(new Type[0]);Console.WriteLine(constructor); 
复制代码

总结

属性将元数据分配给类、字段、方法等。元数据在构建项目时被编译并描述元素而不是元素的数据。我们可以继承 Attribute 类来自定义属性,并使用 AttributeUsage 属性限制属性的使用范围,并通过反射来获取属性数据。

用户头像

喵叔

关注

还未添加个人签名 2020.01.14 加入

还未添加个人简介

评论

发布
暂无评论
C#中的属性