1:什么是特性?
特性就是特有属性 特质属性,自定义的一些规则。类似于注释说明,但是又是程序中需要识别的内容需要处理。
我个人理解就是方法使用说明书 在控制器或者类上【】告知使用规则。
Attribute不是什么“修饰符”,而是一种实例化方式比较特殊的类。
2:为什么要使用特性?
因为项目经常需要一些定制的规则应用于 多个控制器或者多个类上,使用特性也是为了将规则能够更广泛更便捷的使用。
3:特性的使用范围?
定制特性可以应用的目标元素可以为:程序集(assembly)、模块(module)、类型(type)、属性(property)、事件(event)、字段(field)、方法(method)、参数(param)、返回值(return)
首先看一下使用范围
AttributeUsage这个用来专门修饰Attribute的Attribute除了可以控制修饰目标外,还能决定被它修饰的Attribute是否能够随宿主“遗传”以及是否可以使用多个实例来修饰同一个目标!
static void Main(string[] args)
{
Console.WriteLine("Assembly\t\t\t{0}", Convert.ToInt32(AttributeTargets.Assembly));
Console.WriteLine("Module\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.Module));
Console.WriteLine("Class\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.Class));
Console.WriteLine("Struct\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.Struct));
Console.WriteLine("Enum\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.Enum));
Console.WriteLine("Constructor\t\t\t{0}", Convert.ToInt32(AttributeTargets.Constructor));
Console.WriteLine("Method\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.Method));
Console.WriteLine("Property\t\t\t{0}", Convert.ToInt32(AttributeTargets.Property));
Console.WriteLine("Field\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.Field));
Console.WriteLine("Event\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.Event));
Console.WriteLine("Interface\t\t\t{0}", Convert.ToInt32(AttributeTargets.Interface));
Console.WriteLine("Parameter\t\t\t{0}", Convert.ToInt32(AttributeTargets.Parameter));
Console.WriteLine("Delegate\t\t\t{0}", Convert.ToInt32(AttributeTargets.Delegate));
Console.WriteLine("ReturnValue\t\t\t{0}", Convert.ToInt32(AttributeTargets.ReturnValue));
Console.WriteLine("GenericParameter\t\t{0}", Convert.ToInt32(AttributeTargets.GenericParameter));
Console.WriteLine("All\t\t\t\t{0}", Convert.ToInt32(AttributeTargets.All));
Console.WriteLine("\n");
}
使用范围规则很简单 [AttributeUsage(AttributeTargets.Class|AttributeTargets.Field)] 直接[]运用
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false )]
AllowMultiple 该属性标识我们的自定义attribte能在同一语言元素上使用多次 默认false
Inherited是否派生继承这个特性
4:常用特性?
.Net 框架提供了三种预定义特性:
- AttributeUsage
- Conditional
- Obsolete
5: 特性能干嘛?
1)功能性信息:如[Serializable]加在类前表示该类可被序列化。
[Serializable]
public class HumanProperty
2)提示性信息:如[Obsolete]表示该方法已经过时,提醒程序员使用新的替代函数。
[Obsolete("Use another method : Average(), instead!", true)]
public virtual void CalcAverage(int speed)
3)限定性信息:如[Conditional("DEBUG")]表示下面的方法只有在调试模式下才有效。
[Conditional("DEBUG")]
public void UnitTest()
4)描述性信息:如[Description]对所指对象进行详细描述。
public enum CreditCardType
{
[Description("Unknown")]
Unknown,
[Description("Corp Card")]
CC
}
然后就可以通过反射来获取到每个枚举中定义的Description("Unknown") 属性
总结:特性是C#中强大的元数据工具,适用于:
- 标记与描述:如版本信息、开发者注释
- 行为控制:如条件编译、序列化规则
- 框架集成:如Web API路由、ORM字段映射
-
通过合理使用预定义特性或自定义特性,可以提升代码的可维护性和扩展性,同时减少重复代码。开发时需结合反射机制,并注意性能与兼容性问题
6:如何创建自定义规则特性
eg:
新建特性
[AttributeUsage(AttributeTargets.All,AllowMultiple =true)]
public class DebugInfo : Attribute {
private int bugno;
private String developer;
private String lastTime;
public String message;
public DebugInfo(int bugno, string developer, string lastTime) {
this.bugno = bugno;
this.developer = developer;
this.lastTime = lastTime;
}
public int BUGNO {
get {
return bugno;
}
}
public String DEVELOPER {
get {
return developer;
}
}
public String LASTTIME {
get {
return lastTime;
}
}
public String MESSAGE {
get {
return message;
}
set {
message = value;
}
}
}
使用特性
[DebugInfo(2019,"LiuYan","1/17",message ="这是print方法")]
public void MyPrint() {
}
利用反射查看属性
static void Main(string[] args)
{
Type t = typeof(Myprint方法所在的类);
var method = t.GetMethod("MyPrint");
DebugInfo ats = (DebugInfo)method.GetCustomAttribute(typeof(DebugInfo), true);
int bugNo = ats.BUGNO;
String name = ats.DEVELOPER;
String time = ats.LASTTIME;
String message = ats.message;
Console.WriteLine("" + bugNo +"+" + name + " +" + time + " +" + message+"");
Console.ReadKey();
}