特性
## 概念
扩展各种元素(类,方法,属性,字段,枚举)功能的标签,它本身是一个继承Attrbute的类;
## 用法
```
[attribute(positional_parameters, name_parameter = value, ...)]
element
```
## 特性参数的顺序
许多特性都有参数,而这些参数可以是定位参数、未命名参数或命名参数。任何定位参数都必须按特定顺序指定并且不能省略,而命名参数是可选的且可以按任意顺序指定。首先指定定位参数。例如,这三个特性是等效的:
```
[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
```
## 预定义特性(Attribute) .net 框架提供了三种预定义特性
- Obsolete
等于 ObsoleteAttribute,在写特性的时候我们往往可以把后面的Attribute给省略
```
[Obsolete(message)] // 只会给出警告信息不影响编译
[Obsolete(message,iserror)] //编译的时候会直接报错
```
- Conditional
若不符合条件则 直接跳过这个方法不管,直接执行下面的语句
应用场景:
当一个方法失效,又不想一个个删除引用它的方法,那么可以使用这个特性
```
//Conditional位于using System.Diagnostics;
[Conditional(conditionalSymbol)] //语法
//下面三个是常用的,.net 框架定义的
[Conditional("DEBUG")] //处于调试模式下可用
[Conditional("NETCOREAPP")] //是.net Core 可用
[Conditional("NETCOREAPP3_1")] //是.net Core3.1 版本才可用
//我自己定义的
[Conditional("canUsewp")] //这样就不会调用该方法; 若在在引入命名空间之前加入 #define canUsewp,那么该执行就可以被调用
```
补充: 利用 Conditional 属性,程序员可以定义条件方法。Conditional 属性通过测试条件编译符号来确定适用的条件。
当运行到一个条件方法调用时,是否执行该调用,要根据出现该调用时是否已定义了此符号来确定。如果定义了此符号,则执行该调用;否则省略该调用(包括对调用的参数的计算)。使用Conditional是封闭#if和#endif内部方法的替代方法,它更整洁,更别致、减少了出错的机会。
条件方法要受到以下限制:
1. 条件方法必须是类声明或结构声明中的方法。如果在接口声明中的方法上指定Conditional属性,将出现编译时错误。
2. 条件方法必须具有返回类型。
3. 不能用override修饰符标记条件方法。但是,可以用virtual修饰符标记条件方法。此类方法的重写方法隐含为有条件的方法,而且不能用Conditional属性显式标记。
4. 条件方法不能是接口方法的实现。否则将发生编译时错误。
5. 如果条件方法用在“委托创建表达式”中,也会发生编译时错误
- AttributeUsage 这个是最常用的
```
[AttributeUsage(
validon, //规定特性的目标元素。它是枚举器 AttributeTargets 的值的组合。默认值是 AttributeTargets.All,
AllowMultiple=allowmultiple, //(可选)为该特性的 AllowMultiple 属性(property)提供一个布尔值。如果为 true,则该特性是多用的。默认值是 false(单用的)
Inherited=inherited //标志该特性是否可以被派生类所继承 默认true,就是写的都可以被继承
)]
枚举器 AttributeTargets
AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Property|AttributeTargets.Field|AttributeTargets.ConStructor|***
```
## 自定义特性
一个新的自定义特性应派生自 System.Attribute 类,建议特性名称以Attribute结尾;
常用的地方
- 表命名跟实体类命名不一样
- 枚举类型的注释值
- 调用某个方法的日志
- 序列化的标记,有一些仅仅是标记,里面没有内容的,CLR会帮我们处理
-
## 自定义特性常用的一个例子 表名称
```
[AttributeUsage(AttributeTargets.Class)] //应用 AttributeUsageAttribute
public class TableNameAttribute : Attribute //声明特性类 必须是公共类 类的命名建议以Attribute结尾,直接或者间接的继承System.Attribute
{
private string l_strTalbeName = "";
public TableNameAttribute(string a_strTableName) //声明构造函数
{
l_strTalbeName = a_strTableName;
}
public string GetTableName()
{
return l_strTalbeName;
}
}
public static string GetTableName<T>(this T t) where T : new()
{
Type type = t.GetType();
var customAttributes = type.GetCustomAttributes();
foreach (var attribute in customAttributes)
{
if (attribute is TableNameAttribute)
{
TableNameAttribute tableNameAttribute = attribute as TableNameAttribute;
return tableNameAttribute.GetTableName();
}
}
return type.Name;
}
//上面的方法也可以写成这个样子
public static string GetTableName(Type t)
{
TableNameAttribute attribute = Attribute.GetCustomAttribute(t, typeof(TableNameAttribute)) as TableNameAttribute;
return attribute is null ?"": attribute.GetTableName();
}
```
## 如何查看特性的信息
特性被放在 the assembly manifest in the metadata portion of the file中:
- 通过工具
[ MSIL 反汇编程序 (Ildasm.exe)](https://docs.microsoft.com/zh-cn/dotnet/framework/tools/ildasm-exe-il-disassembler)
- 创建自定义程序来检索特性
---
- 编译时:正在编译时,把源代码编译成机器能识别的代码;
比如你用VS点击编译按钮就是编译状态;
比如Java.cs转换JVM能识别的字节码,C# 转换成MSIL语言
- 运行时:代码跑起来了,被装载到内存中去了;
出处:http://www.cnblogs.com/maanshancss/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。所有源码遵循Apache协议,使用必须添加 from maanshancss