這可是我的開篇之作啊,希望大家多多捧場,哈哈。
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 |
可以對模組應用屬性。
注意 |
Module 指的是可移植的可執行檔(.dll 或 .exe),而非 Visual Basic 標準模組。 |
|
|
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架構。好了,這個例子先寫到這裡吧,要工作了,下次介紹反射技術。