转:http://www.cnblogs.com/wenwuxianren/articles/931674.html
这可是我的开篇之作啊,希望大家多多捧场,哈哈。
C#不愧比Java晚出几年,这个东西在Java里没有吧,别看这个小东西,简直就像程序的灵魂一样。为什么C#是自描述的Attribute可谓是功不可没。就连程序集的版本信息,密钥文件全都用它来描述。
正如微软所说:特性可以描述的目标可以是程序集、类、构造函数、委托、枚举、事件、字段、接口、方法、可移植可执行文件模块、参数、属性 (Property)、返回值、结构或其他属性 (Attribute)。简直是无所不能。
被描述的东西就像被注入了灵魂一样。
特性所提供的信息也称为元数据。元数据可由应用程序在运行时进行检查以控制程序处理数据的方式,也可以由外部工具在运行前检查以控制应用程序处理或维护自身的方式。例如,.NET Framework 预定义特性类型并使用特性类型控制运行时行为,某些编程语言使用属性类型表示 .NET Framework 公共类型系统不直接支持的语言功能。
所有特性类型都直接或间接地从 Attribute 类派生。特性可应用于任何目标元素;多个特性可应用于同一目标元素;并且特性可由从目标元素派生的元素继承。使用
AttributeTargets 类可以指定特性所应用到的目标元素。
AttributeTargets 枚举:
All | 可以对任何应用程序元素应用属性。 | |||
Assembly | 可以对程序集应用属性。 | |||
Class | 可以对类应用属性。 | |||
Constructor | 可以对构造函数应用属性。 | |||
Delegate | 可以对委托应用属性。 | |||
Enum | 可以对枚举应用属性。 | |||
Event | 可以对事件应用属性。 | |||
Field | 可以对字段应用属性。 | |||
GenericParameter | 可以对泛型参数应用属性。 | |||
Interface | 可以对接口应用属性。 | |||
Method | 可以对方法应用属性。 | |||
Module | 可以对模块应用属性。
|
|||
Parameter | 可以对参数应用属性。 | |||
Property | 可以对属性 (Property) 应用属性 (Attribute)。 | |||
ReturnValue | 可以对返回值应用属性。 | |||
Struct | 可以对结构应用属性,即值类型。 |
AttributeTargets 用作 AttributeUsageAttribute 的参数,以指定可以对其应用属性的元素类型。
可以通过按位“或”运算组合 AttributeTargets 枚举值来获得首选组合。
下表列出了由 AttributeUsageAttribute 类型公开的成员。
名称 | 说明 | |
---|---|---|
AllowMultiple | 获取或设置一个布尔值,该值指示能否为一个程序元素指定多个指示属性实例。 | |
Inherited | 获取或设置一个布尔值,该值指示指示的属性能否由派生类和重写成员继承。 | |
TypeId | 当在派生类中实现时,获取该 Attribute 的唯一标识符。(从 Attribute 继承。) | |
ValidOn | 获取一组值,这组值标识指示的属性可应用到的程序元素。 |
看了这个有点头晕吧,来个例子看(先来个实体类):
[Talbe("Student")]
public class Student:EntityBase
{
private int sid;
[PrimaryKey(PrimaryKeyType.Identity,"StudentID")]
public int Sid
{
get { return sid; }
set { sid = value; }
}
private string sname;
[PrimaryKey(PrimaryKeyType.Assign,"SName")]
public string Sname
{
get { return sname; }
set { sname = value; }
}
private DateTime inTime = DateTime.Now;
[Colum("InTime")]
public DateTime InTime
{
get { return inTime; }
set { inTime = value; }
}
private double classID;
[Colum("ClassID")]
public double ClassID
{
get { return classID; }
set { classID = value; }
}
}
看到了吧,类上 面和属性上面"[]"里面的就是特性类,再看看这几个特性类的代码吧:
#region 对应表的特性类
[AttributeUsageAttribute(AttributeTargets.Class, Inherited=false,AllowMultiple=false),Serializable]
public class TalbeAttribute:Attribute
{
//保存表名的字段
private string _tableName;
public TalbeAttribute()
{
}
public TalbeAttribute(string tableName)
{
this._tableName = tableName;
}
/// <summary>
/// 映射的表名(表的全名:模式名.表名)
/// </summary>
public string TableName
{
set
{
this._tableName = value;
}
get
{
return this._tableName;
}
}
}
#endregion
#region 对应列的特性类
/// <summary>
/// 映射数据库里列的特性
/// </summary>
[AttributeUsageAttribute(AttributeTargets.Property, Inherited = false, AllowMultiple = false),Serializable]
public class ColumAttribute : Attribute
{
private string _columName;
private int _columSize;
private SpecilDBType _dbType = SpecilDBType.Default;
public ColumAttribute()
{
}
public ColumAttribute(string columName):this()
{
this._columName = columName;
}
public ColumAttribute(string columName, int columSize): this(columName)
{
this._columSize = columSize;
}
public ColumAttribute(string columName, int columSize,SpecilDBType dbType):this(columName,columSize)
{
this._dbType = dbType;
}
public ColumAttribute(string columName, SpecilDBType dbType):this(columName)
{
this._dbType = dbType;
}
//数据库里列的大小
public int ColumSize
{
set
{
this._columSize = value;
}
get
{
return this._columSize;
}
}
//列名
public virtual string ColumName
{
set
{
this._columName = value;
}
get
{
return this._columName;
}
}
//描述一些特殊的数据库类型
public SpecilDBType DbType
{
get { return _dbType; }
set { _dbType = value; }
}
}
#endregion
#region 标识主键列的特性
[AttributeUsageAttribute(AttributeTargets.Property, Inherited = false, AllowMultiple = false),Serializable]
public class PrimaryKey : ColumAttribute
{
private PrimaryKeyType _primaryKeyType = PrimaryKeyType.Identity;
//private SpecilDBType _dbType = SpecilDBType.Default;
public PrimaryKey()
{
}
public PrimaryKey(PrimaryKeyType primaryKeyType, string columName)
{
this._primaryKeyType = primaryKeyType;
this.ColumName = columName;
}
public PrimaryKey(PrimaryKeyType primaryKeyType, string columName, SpecilDBType dbType)
: this(primaryKeyType, columName)
{
this.DbType = dbType;
}
//public override string ColumName
//{
// set
// {
// this._columName = value;
// }
// get
// {
// return this._columName;
// }
//}
/// <summary>
/// 主键类型,默认为自增的
/// </summary>
public PrimaryKeyType PrimaryKeyType
{
set
{
this._primaryKeyType = value;
}
get
{
return this._primaryKeyType;
}
}
}
#endregion
看到了吧,以后就可以通过反射技术来读取每个特性类实例里的属性。这样就可以把一个类跟数据库里的表映射起来了。再通过编成的技术完全可以拼出SQL语句。
我做这个例子就是要带大家做一个ORM持久层框架。有了这个特性类完全就可以做出像Java里的Hibernate的框架,而且不用写任何关于表和实体类的XML配置文件。这 只是开篇,以后我会慢慢的介绍反射的技术,然后带领大家做一个ORM框架。好了,这个例子先写到这里吧,要工作了,下次介绍反射技术。