.Net下Attribute的特性简单入门
已经工作了2个多月,请了几天假,凑足10天,给自己安排一次旅行,虽然是下午的航班,但凌晨就睡不着,跑起来收拾好东西后,毫无睡意.so..有了这篇博文
我相信不少初学者,和我一样,经常看到以下这样的代码
对于图示中红线标注的东西,通过查阅资料,知道叫Attribute(特性).于是Google、百度一番,似乎说这个话题的博文不少,估计看完了也是云里雾里的。ok...鄙人就冒昧,用最简单的办法来尝试学习下 Attribute.
1、Attribute到底是什么?
先不要去看那些一大段的文字说明,Attribute翻译过来:(推荐使用百度的翻译.不错...下面的翻译结果引用自百度词典)
attribute1
名词 n. [C]
2.(人,物,职务等的)标志,象征
对,Attribute没什么复杂的,有这个标记的,就认为这个东东(类、字段)是具有某个标志、象征。没什么复杂的,就如我们在超市购物,商品上有一个条形码的Attribute.
可能有朋友要问了,比如一个商品,条形码为什么不使用一个属性来描述?(请参见属性和Attribute的区别)
这里结合官方的文档,用通俗的话说:
可以通过Attribute将一些额外信息加在一些目标元素上(类,字段,接口等),程序编译的时候就将这些额外的信息系列化程序集的元数据中,当你运行程序的时候可以通过反射技术从程序集元数据中读取这些额外信息,并根据这些额外信息决定你程序的行为。
2、属性和Attribute的区别
先不要考虑那么多,记录这个两个东西没有必然联系。OK..下面,直接用代码的方式进行学习
3、使用.Net已定义好的Attribute
新建一个控制台项目Demo,在新建一个MyClass类
public class MyClass
{
[Obsolete("这是一个旧的方法,请调用新的方法NewMethod")]
public void OldMethod()
{
Console.WriteLine("这是旧方法");
}
[Obsolete("这是一个旧的方法,请调用新的方法NewMethod",true)]
public void OldMethod1()
{
Console.WriteLine("这是旧方法");
}
public void NewMethod()
{
Console.WriteLine("这是新方法");
}
}
我们在Program中编写调用MyClass类的代码
MyClass myclass = new MyClass();
myclass.OldMethod();
myclass.OldMethod1();
Console.ReadKey();
此时,我们编译Demo这个项目,会发现有警告和错误
是不是很神奇,为什么在方法上使用Obsolete这样的定制特性,编译器能够做出相应处理,如在使用标记了Obsolete特性的方法时会发出警告信息,但如果我们自己定制的Attribute时,编译器会做什么处理呢?
4、自定义Attribute
1、先注释掉Program调用MyClass类的测试代码.新建一个类MyFirstAttribute.(这里的类名一定是xxxAttribute,原因:)
定义的Attribute必须直接或间接从公共抽象类System.Attribute派生。所以我们前面Obsolete、STAThread和Serializable都是派生于Attribute。
自定义Attribute的命名规范,其规则是“特性名+Attribute”。
class MyFirstAttribute:Attribute
{
public string Msg { get; set; }
public MyFirstAttribute(string msg)
{
Msg = msg;
}
}
在Demo项目中新增一个类Person,使用我们自定义的的MyFirstAttribute类能够应用在这个类上
[MyFirstAttribute("自定义第一个Attribute")]
class Person
{
}
我们给Person类使用了自定义的MyFirstAttribute标记后,程序应该怎样获取到Person的MyFirstAttribute内容呢?在Program类中编写测试代码
var attributes = typeof(Person).GetCustomAttributes(typeof(MyFirstAttribute), true);
MyFirstAttribute myAttribute = attributes[0] as MyFirstAttribute;
if (myAttribute != null)
{
Console.WriteLine(myAttribute.Msg);
}
编译且运行Demo项目,程序运行结果
到这里,我们就自定义了一个MyFirstAttribute,并且成功的调用测试了.回头看下这简单的代码,会发现一个模型,就是我们自定义了一个Attribute类,当应用于目标元素上(类,字段,接口等),我们在写程序去获取(反射)目标元素时,解析我们的Attribute类,再实现Attribute的功能代码.
比如,我想实现这样的效果:我们给Person类中的属性打上一个自定义的标记,在使用了自定义的标记属性,在将Person对象写到文件的时候,打了自定义标记的,就保存到文件.否则就不保存.
Ok.先定义一个Attribute(注意:命名规则和继承关系)
class WriteFileAttribute:Attribute
{
}
在Person类中,新增几个属性代码,并使用标记
class Person
{
[WriteFile]
public int Id { get; set; }
[WriteFile]
public string Name { get; set; }
/// <summary>
/// 密码,不使用标记
/// </summary>
public string Pwd { get; set; }
[WriteFile]
public int Age { get;set;}
}
然后我们Program中编写调用Person类的代码
Person per1 = new Person() { Age = 20, Id = 1, Name = "Winloa", Pwd = "123" };
StringBuilder content = new StringBuilder();
//分析Person中那些属性使用了WriteFileAttribute,如果使用了,就将此属性值写入到文件
Type typePerson = per1.GetType();
PropertyInfo [] propArry= typePerson.GetProperties();
foreach (var item in propArry)
{
object [] obj=item.GetCustomAttributes(typeof(WriteFileAttribute), false);
if (obj.Length > 0)
{
//说明该属性使用了WriteFileAttribute标记
content.Append(item.Name + "\t" + item.GetValue(per1, null)+"\r\n");
}
}
File.WriteAllText("D:\\Attribute.txt", content.ToString());
然后我们编译Demo项目并且运行.我们发现在D盘根目录下有一个Attribute.txt文件
Person类中的Pwd属性并没有使用WriteFileAttribute,所以在保存到文件时,没有记录下来。
5、总结
Attribute通俗的说,就是一个标记,这些标记有.net系统提供的,我们也可以自定义,自定义的Attribute类,应该注意:命名规则和继承关系
然后我们使用了自定义的Attribute类,应该有响应的解析类,要不然自定义的Attribute程序也不知道如何调用
比如我们想把前面的Person类的对象持久化到数据库(这里需要考虑主键、数据库兼容等情况)
1、自定义一个Attribute--->WriteDataBaseAttribute.cs
2、在Person中使用WriteDataBaseAttribute
3、写一个解析WriteDataBaseAttribute类,在WriteDataBaseAttribute中完成对数据库的CRUD