定制Attribute
目录
- Attribute是什么
- 自定义Attribute
一、Attribute是什么
将一些附加信息与制定目标相关联的方式。编译器在元数据中生成这些额外的信息。也叫做特性。
比如之前文章中提到的:枚举类型与位运算。也是向枚举类型定制了[FlagsAtribute]特性,将枚举类型作为一个位标识集合使用。
[Flags]
public enum Options
{
None=,
Insert = , //二进制: 0001
Update = , //二进制: 0010
Save = , //二进制: 0100
Delete = , //二进制: 1000
Query = //二进制:10000
}
Attribute使用[]进行标记说明,会在某个目标元素的上方,这里的Flags是FlagsAttribute的简写。
1、那我们F12看一下[Falags]的定义:
public class FlagsAttribute : Attribute
{
// 摘要:
// 初始化 System.FlagsAttribute 类的新实例。
public FlagsAttribute();
}
FlagsAttribute直接或者间接继承自Attribute。当然我们也可以看出所说的Flags特性就是一个类的实例。既然是类的实例,需要有构造方法,所以我们也就看到了上面的构造函数FlagsAttribute。
我们写的[Falags]实际是调用了public FlagsAttribute();构造函数。
2、那我们再来一个例子,先不管这句话什么意思,或者作用是什么。
[DllImport("Json.Text", CharSet = CharSet.Auto,BestFitMapping=true)]
public void GetNewMail(string from, string to, string msg)
{
MailInfo newmailinfo = new MailInfo(from, to, msg);
OnNewMail(newmailinfo); }
我们同样F12看一下定义:
public sealed class DllImportAttribute : Attribute
{
public bool BestFitMapping; public CharSet CharSet; public DllImportAttribute(string dllName); public CallingConvention CallingConvention;
public string EntryPoint;
public bool ExactSpelling;
public bool PreserveSig;
public bool SetLastError;
public bool ThrowOnUnmappableChar;
public string Value { get; }
}
但是这里的构造函数是接受一个String类型的参数,但是我们调用时却是这样写
[DllImport("Json.Text", CharSet = CharSet.Auto,BestFitMapping=true)]
这里的第一个参数是狗咱好书默认的参数,而后面的是DllImportAttribute类中的公共属性或者公共字段,那就不难理解我们这里直接调用了里面的两个公共属性并给他们做了赋值。
那就不难理解这些为什么会这样写了:
[Table("Menu", Schema = "admin")]
3、多个Attribute组合
[Flags]
[DllImport("Json.Text", CharSet = CharSet.Auto, BestFitMapping = true)]
public enum Options
{
None=,
Insert = , //二进制: 0001
Update = , //二进制: 0010
Save = , //二进制: 0100
Delete = , //二进制: 1000
Query = //二进制:10000
}
我们也可以这样写,两个特性用,分隔:
[Flags, DllImport("Json.Text", CharSet = CharSet.Auto, BestFitMapping = true)]
二、自定义Attribute
如何根据需求定义我们自己的特性,通过以上的了解,我们至少知道我们的Attribute直接或者间接继承基类Attribute,并且要有实例构造函数进行构造。也可以定义一些需要的公共属性等等。
当然命名也要符合约定以Attribute为后缀。
[System.AttributeUsage(System.AttributeTargets.Class |System.AttributeTargets.Struct,
AllowMultiple = true,
Inherited = true
)]
public class MarkAttribute : System.Attribute
{
public string appname;
public double version = 1.0; public MarkAttribute(string appname)
{
this.appname = appname;
}
}
我们定义一个MarkAttribute,我们约定我们自定义的特性符合AttributeUsage特性:目标元素为类或者结构,允许多个属性,可以继承。
我们自己定义的MarkAttribute,有两个公共字段appname和version。并有一个构造函数。
这样我们这样运用自己的简单的特性:
[Mark("Apple", version = 2.0)]
public class APP
{
}
既然定义了,也标注到了特定的目标上,剩下的就是我们调用了。
通过反射来调用我们定义的特性:
System.Attribute[] attrs = System.Attribute.GetCustomAttributes(typeof(MarkAttribute)); // Reflection. foreach (System.Attribute attr in attrs)
{
if (attr is MarkAttribute)
{
MarkAttribute m = (MarkAttribute)attr;
System.Console.WriteLine(" {0}, 版本 {1:f}",m.appname,m.version);
}
}
这样我们就完成了我们自定义的特性并完成调用。
但是编译器是如何调用Attribute的呢?
编译器检测到一个元素应用到一个元素应用到attribute的时候,编译器会调用attribute类的构造器,向他传递参数,就构造了一个实例,
编译器再根据特定的语法对公共字段和属性进行初始化,并将这些信息驻留到元数据中。这只是会生成相关的元数据。
那编译器又是如何调用特性的呢?
和我们上面的例子类似,通过反射。我们知道所有的特性都继承自Attribute,我们F12转到定义可以看到,基类Attribute主要有三组方法组成:
GetCustomAttribute:返回应用的一个特性.
GetCustomAttributes:返回应用的多个特性.
IsDefined:检测判断元素是否应用Attribute.
总结,我们知道什么是Attribute,并可以自定义Attribute.
最新文章
- spring mvc重定向方法
- 常用数据库高可用和分区解决方案(1) — MySQL篇
- Hive 中的分号问题
- Centos 上使用Mono+MVC5+WebApi+Sqlite
- ZooKeeper 编程(一)
- 关于Activity销毁,而绘制UI的子线程未销毁出现的问题
- 微信支付开发(12) 认清微信支付v2和v3
- 3732 Ahui Writes Word
- Python用format格式化字符串
- 缓存管理Memorycache 的使用
- HOJ1008
- MYSQL 好文章集锦
- swift 有些语法还是不支持。
- C# .NETWEB开发6大内置对象
- linux下配置ip地址四种方法(图文)
- java操作impala
- MSIL实用指南-闭包的生成和调用
- 小程序 表单 获取 formId
- CPU高速缓存
- Http原理与实践
热门文章
- [置顶] JUnit入门教程(二)
- Linux虚拟文件系统VFS解决
- C# 引用类型与值类型的区别
- ZOJ--3631--Watashi&;#39;s BG【枚举】
- 什么是比特币(Bitcoin)?
- Docker创建支持ssh服务的容器和镜像
- quick 2.23 它们的定义c++代码lua与总结的一些细节
- How to fix Column 'InvariantName' is constrained to be unique 解决办法!
- 【甘道夫】HBase开发环境搭建过程中可能遇到的异常:No FileSystem for scheme: hdfs
- Web指纹识别目的Discuz识别+粗糙的版本演绎