特性
Contents
特性
特性是什么
- 特性是一种允许我们向程序的程序集添加元数据的语言结构
- 它是用于保存程序结构信息的某种特殊类型的类
- 特性提供功能强大的方法以将声明信息与C#代码(类型、方法、属性等)相关联
- 特性与程序实体关联后,即可在运行时使用反射查询特性信息
- 特性的目的是告诉编译器把程序结构的某族元素嵌入程序集中
- 它可以放置在几乎所有的声明中(类、变量、函数等)
- 特性的本质是个类 我们可以利用特性类为元数据添加额外信息 之后可以通过反射来获取这些信息
自定义特性
需要继承特性基类Attribute
//本质是一个类 类名中的Attribute会被省略
class MyCustomAttribute : Attribute{
//特性中的成员 一般根据需求来写
public string info;
public MyCustomAttribute(string info){
this.info = info;
}
}特性的使用
- 基本语法:[特性名(参数列表)]
- 本质上 就是在调用特性类的构造函数
- 写在 类、函数、变量的上一行,表示他们具有该特性信息
[MyCustom("这是我自己写的特性")]
class MyClass{
[MyCustom("特性可以写在成员变量前面")]
public int value;
[MyCustom("特性可以写在函数前面")]
public void TestFun([MyCustom("特性可以写在参数前面")] int a){
}
}
MyClass mc = new MyClass();
Type type = mc.GetType();
//判断是否使用了某个特性
//参数一:特性的类型
//参数二:是否搜索继承链(属性和事件忽略此参数)
if(type.IsDefined(typeof(MyCustomAttribute),false)){
Console.WriteLine("该类型应用了MyCustom特性")
//获取type元素中的所有特性 参数是否搜索继承链
object[] array = type.GetCustomAttributes(true);
foreach(var item in array){
if(item is MyCustomAttribute){
Console.WriteLine((item as MyCustomAttribute).info);
}
}
}为特性类 加特性 限制其使用范围
- 可在特性类前添加AttributeUsage特性
- AttributeUsage构造方法参数:
- AttributeTargets 限制特性能够用在那些地方
- AllowMultiple 是否允许多个特性实例用在同一个目标上
- Inherited 特性是否能被派生类和重写成员继承
- AttributeUsage构造方法参数:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct , AllowMultiple = true , Inherited = true)]
class MyCustomAttribute : Attribute{
//特性中的成员 一般根据需求来写
public string info;
public MyCustomAttribute(string info){
this.info = info;
}
}系统自带特性
过时特性Obsolete
- 用于提示用户使用的方法成员等已经过时 建议使用新方法
- 一般加载函数前的特性
class Test{
//参数1提示 参数2 true-使用时会报错 false-警告
[Obsolete("OldSpeak已经过时,请使用新方法",false)]
public void OldSpeak(){
}
}调用者信息特性
- CallerFilePath 哪个文件调用
- CallerLineNumber 哪一行调用
- CallerMemberName 哪个函数调用
- 调用这个函数或者变量时 会自动打印信息出来 很少使用
条件编译特性
- Conditional 他会和预处理指令 #define配合使用
- 需要引用命名空间System.Diagnostics;
- 主要可以用在一些调试代码上 有时想执行有时不想执行的代码
#define test
class Test(){
[Conditional("test")] //有test这个符号这个方法才会被执行
static void Func(){
}
}外部dll包函数特性
- DllImport用来标记非.Net(c#)函数,表明该函数在一个外部的dll中定义
- 一般用来调用 C或者C++的dll包中的函数
- 需要引用命名空间 System.Runtime.InteropServices
class Test(){
[DllImport("dll包路径名")]
static void extern int Add(int a,int b)();
//相当于是把这个dll包里的方法 映射到了c#中来
}