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(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#中来
}