[C#] Attribute
什么是Attribute?我们为什么需要Attribute?
Attribute是一段附加信息,该信息可以附加在方法,类,名称空间,程序集上。例如下面的例子中,将Method1设为“Obsolete”属性。
public class MyClass { [Obsolete] public void Method1() { } public void NewMethod() { } }
我们在代码中调用Method1,这个方法,
简单的说,Attribute其实没有做任何代码相关的工作,只是给开发者一段直观的提示信息。在“Obsolete” 属性上,如果你需要给开发者更多信息。例如:
[Obsolete("Please use NewMethod")] public void Method1() { }
如果需要限制开发者使用Method1,可以在Obsolete属性中,传递“true”,代码如下:
[Obsolete("Please use NewMethod", true)] public void Method1() { }
此时再调用Method1,则编译时直接报错,而不是一个Warning信息。
怎么创建自定义Attribute
上述代码中使用的Obsolete属性是系统提供的。自定义Attribute只需要继承Attribute类即可。例如:
public class HelpAttribute : Attribute { public string HelpText { get; set; } } [Help(HelpText ="This is a class")] public 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() { } }
自定义了一个HelpAttribute,然后将它应用在类/方法/属性上面。
是否可以限制一个自定义Attribute只应用在方法或者属性上面?
对HelpAttribute类进行如下修改即可,
[AttributeUsage(AttributeTargets.Method)] public class HelpAttribute : Attribute { public string HelpText { get; set; } }
在HelpAttribute上面添加AttributeUsage属性,将AttributeTargets设置为Method即可。AttributeTargets是一个枚举类型,更多信息:
https://msdn.microsoft.com/en-us/library/system.attributetargets(v=vs.110).aspx
除了可以描述一段信息之外,Attribute还可以做什么?
例如下面的例子,限制一个字段长度的Attribute。定义一个CheckAttribute,并在Customer的CustomerCode的长度,
[AttributeUsage(AttributeTargets.Property)] public class CheckAttribute : Attribute { public int MaxLength { get; set; } } public class Customer { private string _customerCode; [Check(MaxLength = 10)] public string CustomerCode { get { return _customerCode; } set { _customerCode = value; } } [Help(HelpText ="This is a method")] public void Add() { } }
下面使用反射(Reflection)来读取Attribute的值,并做校验,
Customer obj = new Customer(); obj.CustomerCode = "12345678901"; // Reflect // Get the type of the object Type type = obj.GetType(); // Loop through all properties foreach (PropertyInfo p in type.GetProperties()) { foreach (Attribute atr in p.GetCustomAttributes(false)) { CheckAttribute c = atr as CheckAttribute; if(c != null) { if(p.Name == "CustomerCode") { // Do the length check and raise exception accordingly if(obj.CustomerCode.Length > c.MaxLength) { throw new Exception("Max length issues."); } } } } }
自定义Attribute是否可以被继承?
可以。例如,自定义一个CheckExAttribute继承自CheckAttribute
如果不想被其它Attribute继承,使用Inherited =false标记即可,
[AttributeUsage(AttributeTargets.Property,Inherited =false)] public class CheckAttribute : Attribute { public int MaxLength { get; set; } }
如果一个属性只想被调用一次,可以使用AllowMultiple=false
[AttributeUsage(AttributeTargets.Property,AllowMultiple=false)] class Check : Attribute { public int MaxLength { get; set; } }
感谢您的阅读!