.net編譯器的任務之一就是為所有定義和引用的型別生成元資料描述。除了程式集中標準的元資料外,.net平台還支援特定(attribute)把更多的元資料嵌入到程式集中。
.net特性擴充套件了抽象的system.attribute基類,.net中有很多預定義的特性,例如:[dllimport]、[obsolete]和[serializable]等等。
看乙個obsolete使用的例子,obsolete特性用來標記不用的類或成員,當其他程式試圖訪問該項的時候,將會得到乙個警告或錯誤描述。
static使用上面的**,我們就會的到乙個錯誤訊息,提示我們不應該在使用這個方法了class
stringutil
[obsolete(
"this legacy method should not be used
", true
)]
public
static
string legacyreversestring(string
str)
}class
program
}
當然,我們也可以通過**來新增自定義特性,在開始自定義特性之前,我們需要知道以下概念。
在**中,我們可以建立自定義的特性型別,但是這個型別一定要直接或間接從system.attribute派生。下面我們就定義了乙個tableattribute特性:
[attributeusage(attributetargets.class, inherited=false, allowmultiple=false注意:對乙個特性類名使用attribute字尾是乙個慣例。然而,當我們把特性新增到乙個程式實體,可以選擇省略atrribute字尾。編譯器會首先在system.attribute的派生類中查詢被新增的特性類。如果沒有找到,那麼編譯器會新增 attribute字尾繼續查詢。)]public
class
tableattribute : attribute
public tableattribute(string
tablename)
public
string tablename
}
例如:當我們在**中使用的時候,特性表現為[obsolete],但是實際上型別是obsoleteattribute,而不是**中的obsolete。當.net framework進行名稱轉換的時候,所有的.net特性(包括自定義特性)都將加上乙個attribute標記的字尾。
在上面的自定義特性中,有下面一行**,我們給自定義特性應用了乙個attributeusage特性。
[attributeusage(attributetargets.class, inherited=false, allowmultiple=false)]attributeusage類是乙個預定義特性類,通過這個特性,我們可以控制自定義特性的使用,它描述了乙個定製特性如和被使用。
[serializable]通過**可以看到,attributeusage有三個屬性:[attributeusage(attributetargets.class, inherited = true
)][comvisible(
true
)]public
sealed
class
attributeusageattribute : attribute
public
bool inherited
public attributetargets validon
}
從上面的介紹可以看到,建立自定義特性的大概步驟:
宣告特性類,由 system.attribute 直接或間接派生
使用attributeusage特性來控制自定義特性
宣告特性類建構函式
當我們使用特性的時候,只是給程式集新增了一些元資料。當結合反射使用的時候,特性就能發揮很大的作用了。
下面看乙個特性和反射結合的例子,在例子中自定義了table和column特性,然後把這些特性應用到了我們的user型別上面;然後結合乙個自定義的orm型別,將物件的inster()操作轉換成sql語句。
namespace**的執行結果為:attributetest
public tableattribute(string
tablename)
public
string tablename
}[attributeusage(attributetargets.property, inherited=false, allowmultiple=false
)]
public
class
columnattribute:attribute
public columnattribute(string
columnname)
public columnattribute(string
colunmname, dbtype dbtype)
public
string columnname
public dbtype dbtype
}public
class
customizeorm}}
foreach (var item in
columnvaluedict)
sqlstr.remove(sqlstr.length - 1, 1);"
) values('");
foreach (var item in
columnvaluedict)
sqlstr.remove(sqlstr.length - 2, 2);"
)"); console.writeline(sqlstr.tostring());}}
[table(
"users")]
public
class
user
[column(columnname="
name
",dbtype=dbtype.string)]
public
string username
[column(columnname = "
age", dbtype =dbtype.int32)]
public
int age
}class
program
;customizeorm.insert(user);
console.read();}}
}
從這個例子中可以看到,通過特性給程式集加入的元資料,可以在執行時被反射程式得到並使用。
通過il**可以看到特性的簡化,**中我們使用table、column對user型別進行修飾,在il**中都加上了attribute字尾;同時還可以看到,這些特性都變成了user型別的元資料。
通過本文介紹了.net特性,同時介紹了自定義特性需要的基本知識。
特性本身只是給程式集新增一些元資料,當結合反射使用的時候,這些被新增的元資料才能發揮更大的作用。
C 反射特性 一)
using system using system.collections.generic using system.linq using system.text using system.reflection namespace reflectionexam set private string ...
C 反射技術簡介
如果你要獲取到這個類的物件例項可以這麼做 以string類為例子 string str system.string string exp string activator.createinstance str 如果你要得到這個類的型別資訊可以這麼做 type exptype type.gettype...
反射與特性
反射 程式在執行時,可以檢視其它程式集或其本身的元資料。乙個執行的程式檢視本身的元資料或者其他程式集的元資料的行為叫做反射。myclass.cs class myclass 定義乙個用來反射查詢的元資料 public void test program.cs static void main str...