概念
特性本质上是个类,利用特性类为元数据添加额外信息,之后通过反射来获取这些信息。
用法:
#define func
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Diagnostics;
namespace 特性
{
//知识点4 限制自定义特性的范围
//参数一:AttributeTargets用于类、变量还是方法,用|隔开
//参数二:AllowMultiple是否可以为一个类添加多个特性
//参数三:Inherited是否可以让派生类和重写成员继承
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
//知识点2 自定义特性
class MyCustomAttribute : Attribute
{
public string str;
public MyCustomAttribute(string str)
{
this.str = str;
}
public void TestFunc()
{
Console.WriteLine("特性的方法");
}
}
#region 知识3 特性的使用
//基本语法:
//[特性名(参数列表)]
//本质上是调用特性类的构造函数,写在类、函数、变量上一行
[MyCustom("自己的特性类")]//受AttributeUsage中的AllowMultiple影响
[MyCustom("自己的特性类")]//特性名后缀Attribute系统自动省略
class MyClass
{
[MyCustom("特性成员变量")]
public int value;
//[MyCustom("特性成员函数")]
public void TestFunc(int a)
{
}
}
#endregion
#region 知识5 系统自带特性 过时特性
//Obsolete,提示该方法已过时
class MyTest2
{
//第一个参数为提示语句
//第二个参数为true则调用时报错,false则警告
[Obsolete("该方法已过时",false)]
public void oldSpeak()
{
}
}
#endregion
#region 知识6 系统自带特性 调用者信息特性
//一般用在try catch中的catch打印错误信息
//需引入using System.Runtime.CompilerServices;
//CallerFilePath为文件路径,CallerLineNumber为哪一行调用,CallerMemberName哪个函数调用
class MyTest6
{
public void SpeakCaller(string str,[CallerFilePath]string filename="",
[CallerLineNumber]int line=0,[CallerMemberName]string methodname="")
{
Console.WriteLine(str);
Console.WriteLine("调用文件路径:"+ filename);
Console.WriteLine("调用行:" + line);
Console.WriteLine("调用方法名:" + methodname);
}
}
#endregion
#region 知识8 系统自带特性 外部dll包特性
//用于调用c或c++的dll包中的方法,不做介绍
#endregion
class Program
{
#region 知识点7 系统自带特性 条件编译特性
//条件编译特性Conditional
//与define配合,需引入
//有定义func,函数Func才会被编译
[Conditional("func")]
static void Func()
{
Console.WriteLine("func");
}
#endregion
static void Main(string[] args)
{
#region 特性的使用
MyClass mc = new MyClass();
Type t = mc.GetType();
//判断该类是否使用了某个特性
//参数一:特性类型 参数二:是否搜索父亲有这个特性
if(t.IsDefined(typeof(MyCustomAttribute),false))
{
Console.WriteLine("该类型应用了MyCustom特性");
}
//获取Type元数据的所有特性
//GetCustomAttributes里的参数和上面意思一样
object[] array = t.GetCustomAttributes(true);
for(int i=0;i<array.Length;i++)
{
if(array[i] is MyCustomAttribute)
{
Console.WriteLine((array[i] as MyCustomAttribute).str);//str=自己的特性类
(array[i] as MyCustomAttribute).TestFunc();
}
}
MyTest2 myTest2 = new MyTest2();
myTest2.oldSpeak();
MyTest6 myTest6 = new MyTest6();
myTest6.SpeakCaller("abc");
Func();
#endregion
}
}
}