属性在编程中的使用和自定义

属性是编程中用于提供额外信息的一种机制。它们可以附加到方法、类、命名空间、程序集等上。属性使得开发者在调用方法或访问类时,能够直观地看到相关信息,并据此做出相应的操作。

例如,下面是一个简单的类,其中“Method1”方法被“Obsolete”属性装饰。属性通过使用“[]”符号来定义。因此,当开发者开始在这个类中编码时,他们会收到警告,提示“Method1”已经过时,现在应该使用“NewMethod1”。

public class Class1 { [Obsolete] public void Method1() { } public void NewMethod1() { } }

同样地,如果有人尝试创建“Class1”的对象,他们会在工具提示中收到警告,提示“Method1”已经过时,应该使用“NewMethod1”。简而言之,属性是嵌入在代码中的一小段信息,开发者可以直观地看到这些信息。

如果想向开发者显示一些信息,可以在“Obsolete”属性中传递消息,如下所示:

[Obsolete("Please use NewMethod1")] public void Method1() { }

如果想更加严格,不允许开发者使用该方法,可以向“Obsolete”属性传递“true”,如下所示:

[Obsolete("Please use NewMethod1", true)] public void Method1() { }

现在,如果开发者尝试调用“Method1”,他们将收到错误,而不仅仅是一个简单的警告。

如何创建自定义属性

之前讨论的“Obsolete”属性是一个现成的属性。要创建自定义属性,需要继承自Attribute类。下面是一个简单的“HelpAttribute”,它有一个“HelpText”属性。

class HelpAttribute : Attribute { public string HelpText { get; set; } }

“HelpAttribute”被应用到“Customer”类上,如下所示。现在,当开发者看到这个类时,他们可以直观地看到信息。

[Help(HelpText = "This is a class")] class Customer { private string _CustomerCode; [Help(HelpText = "This is a property")] public string CustomerCode { get { return _CustomerCode; } set { _CustomerCode = value; } } [Help(HelpText = "This is a method")] public void Add() { } }

能否将自定义属性限制为仅用于方法

通过使用“AttributeUsage”和“AttributeTargets”,可以将属性限制在特定的部分,如类、方法、属性等。下面是一个简单的自定义属性,现在仅限于方法。

[AttributeUsage(AttributeTargets.Method)] class HelpAttribute : Attribute { public string HelpText { get; set; } }

如果尝试将上述属性应用到类或属性上,将得到编译时错误。也可以将属性限制为类、构造函数、程序集等。以下是可以限制属性的一些可能性。

除了信息,属性还能做什么

到目前为止讨论的一个用途是为开发者提供信息,以便他们在编码时可以看到并据此做出决策。另一个用途是可以通过反射编程方式读取信息并据此采取行动。

例如,下面是一个自定义属性,它描述了类属性的字符长度。

[AttributeUsage(AttributeTargets.Property)] class Check : Attribute { public int MaxLength { get; set; } }

下面是一个客户类,该属性被装饰,提供了“CustomerCode”属性的最大长度不能超过10个字符的信息。

class Customer { private string _CustomerCode; [Check(MaxLength = 10)] public string CustomerCode { get { return _CustomerCode; } set { _CustomerCode = value; } } }

接下来的代码将动态地遍历每个属性的属性,并进行长度验证检查。

第一步是创建客户类的实例。

// 创建Customer类的实例 Customer obj = new Customer(); obj.CustomerCode = "12345678901";

第二步是获取对象的“Type”。因为一旦获得了对象的类型,就可以浏览对象的属性、方法等。

// 获取对象的类型 Type objtype = obj.GetType();

使用“Type”对象,遍历所有属性及其属性。

// 遍历所有属性 foreach (PropertyInfo p in objtype.GetProperties()) { // 对于每个属性,遍历所有属性 foreach (Attribute a in p.GetCustomAttributes(false)) { } }

一旦获得了属性,可以进行长度检查,并相应地引发异常。

// 遍历所有属性 foreach (PropertyInfo p in objtype.GetProperties()) { // 对于每个属性,遍历所有属性 foreach (Attribute a in p.GetCustomAttributes(false)) { Check c = (Check)a; if (p.Name == "CustomerCode") { // 进行长度检查,并相应地引发异常 if (obj.CustomerCode.Length > c.MaxLength) { throw new Exception("Max length issues"); } } } }

属性是否被继承

是的,它们在子类中被继承。

如果想要防止某些属性被继承怎么办

在“AttributeUsage”中有“Inherited”属性,如果将其设置为false,那么这些属性将不会被继承到子类中。

[AttributeUsage(AttributeTargets.Property, Inherited = false)] class Check : Attribute { public int MaxLength { get; set; } }

如果指定“AllowMultiple”为true,它可以在同一程序中多次使用。

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] class Check : Attribute { public int MaxLength { get; set; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485