屬性的使用
為了對屬性進(jìn)行測試,我們創(chuàng)建一個(gè)名字為MyMath的簡單類,并給它添加二個(gè)函數(shù),然后給它指定bugfix屬性。
[BugFixAttribute(121,"JesseLiberty","01/03/05")]
[BugFixAttribute(107,"JesseLiberty","01/04/05",
Comment="Fixedoffbyoneerrors")]
publicclassMyMath
這些數(shù)據(jù)將與元數(shù)據(jù)存儲在一起。下面是完整的源代碼及其輸出:
自定義屬性
usingSystem;
//創(chuàng)建被指派給類成員的自定義屬性
[AttributeUsage(AttributeTargets.Class,
AllowMultiple=true)]
publicclassBugFixAttribute:System.Attribute
{
//位置參數(shù)的自定義屬性構(gòu)造器
publicBugFixAttribute
(intbugID,
stringprogrammer,
stringdate)
{
this.bugID=bugID;
this.programmer=programmer;
this.date=date;
}
publicintBugID
{
get
{
returnbugID;
}
}
//命名參數(shù)的屬性
publicstringComment
{
get
{
returncomment;
}
set
{
comment=value;
}
}
publicstringDate
{
get
{
returndate;
}
}
publicstringProgrammer
{
get
{
returnprogrammer;
}
}
//專有成員數(shù)據(jù)
privateintbugID;
privatestringcomment;
privatestringdate;
privatestringprogrammer;
}
//把屬性指派給類
[BugFixAttribute(121,"JesseLiberty","01/03/05")]
[BugFixAttribute(107,"JesseLiberty","01/04/05",
Comment="Fixedoffbyoneerrors")]
publicclassMyMath
{
publicdoubleDoFunc1(doubleparam1)
{
returnparam1+DoFunc2(param1);
}
publicdoubleDoFunc2(doubleparam1)
{
returnparam1/3;
}
}
publicclassTester
{
publicstaticvoidMain()
{
MyMathmm=newMyMath();
Console.WriteLine("CallingDoFunc(7).Result:{0}",
mm.DoFunc1(7));
}
}
輸出:
CallingDoFunc(7).Result:9.3333333333333339
象我們看到的那樣,屬性對輸出絕對沒有影響,創(chuàng)建屬性也不會影響代碼的性能。到目前為止,讀者也只是在聽我論述有關(guān)屬性的問題,使用ILDASM瀏覽元數(shù)據(jù),就會發(fā)現(xiàn)屬性確實(shí)是存在的。
映射
在許多情況下,我們需要一種方法,能夠從元數(shù)據(jù)中訪問屬性,C#提供了對映射的支持以訪問元數(shù)據(jù)。通過初始化MemberInfo類型對象,System.Reflection名字空間中的這個(gè)對象可以用來發(fā)現(xiàn)成員的屬性,對元數(shù)據(jù)進(jìn)行訪問。
System.Reflection.MemberInfoinf=typeof(MyMath);
對MyMath類型調(diào)用typeof操作符,它返回一個(gè)由繼承MemberInfo而生成的Type類型的變量。
下一步是對MemberInfo對象調(diào)用GetCustomAttributes,并將希望得到的屬性的類型作為一個(gè)參數(shù)傳遞給GetCustomAttributes??荚嚧筇崾緦⒌玫揭粋€(gè)對象數(shù)組,數(shù)組的每個(gè)成員的類型都是BugFixAttribute。
object[]attributes;
attributes=Attribute.GetCustomAttributes(inf,typeof(BugFixAttribute));我們就可以遍歷這個(gè)數(shù)組了,打印BugFixAttribute對象的數(shù)組,代碼下所示:
屬性的打印
publicstaticvoidMain()
{
MyMathmm=newMyMath();
Console.WriteLine("CallingDoFunc(7).Result:{0}",
mm.DoFunc1(7));
//獲取成員信息并使用它訪問自定義的屬性
System.Reflection.MemberInfoinf=typeof(MyMath);
object[]attributes;
attributes=
Attribute.GetCustomAttributes(inf,typeof(BugFixAttribute));
//遍歷所有的屬性
foreach(Objectattributeinattributes)
{
BugFixAttributebfa=(BugFixAttribute)attribute;
Console.WriteLine("\nBugID:{0}",bfa.BugID);
Console.WriteLine("Programmer:{0}",bfa.Programmer);
Console.WriteLine("Date:{0}",bfa.Date);
Console.WriteLine("Comment:{0}",bfa.Comment);
}
}
類型發(fā)現(xiàn)
我們可以通過映象的方法來研究一個(gè)組合實(shí)體的內(nèi)容,如果要建立需要顯示組合體內(nèi)部信息的工具或動(dòng)態(tài)地調(diào)用組合體中的途徑,這一方法是非常有用的。
通過映象的方法,我們可以知道一個(gè)模塊、方法、域、屬性的類型,以及該類型的每個(gè)方法的信號、該類支持的界面和該類的超級類。我們可以通過如下的形式,用Assembly.Load靜態(tài)方法動(dòng)態(tài)地加載一個(gè)組合體:
publicstaticAssembly.Load(AssemblyName)
然后,可以將它傳遞到核心庫中。
Assemblya=Assembly.Load("Mscorlib.dll");
一旦加載了組合體,我們可以通過調(diào)用GetTypes返回一個(gè)Type對象數(shù)組。Type對象是映射的核心,它表示類、界面、數(shù)組、值和枚舉等的類型定義。
Type[]types=a.GetTypes();
組合休會返回一個(gè)類型的數(shù)組,我們可以使用foreach-loop結(jié)構(gòu)顯示該數(shù)組,其輸出將有好幾頁文檔之多,下面我們從中找一小段:
TypeisSystem.TypeCode
TypeisSystem.Security.Util.StringExpressionSet
TypeisSystem.Text.UTF7Encoding$Encoder
TypeisSystem.ArgIterator
TypeisSystem.Runtime.Remoting.JITLookupTable
1205typesfound
我們得到了一個(gè)內(nèi)容為核心庫中類型的數(shù)組,可以將它們都打印出來,該數(shù)組將有1205個(gè)項(xiàng)。
對一種類型映射我們也可以對組合體中一種類型進(jìn)行映射。為此,我們可以使用GetType方法從組合體中解析出一個(gè)類型:
publicclassTester
{
publicstaticvoidMain()
{
//檢查一個(gè)對象
TypetheType=Type.GetType("System.Reflection.Assembly");
Console.WriteLine("\nSingleTypeis{0}\n",theType);
}
}
輸出如下所示:
SingleTypeisSystem.Reflection.Assembly
發(fā)現(xiàn)成員
我們還可以得到所有成員的類型,顯示所有的方法、屬性、域,下面的代碼演示了實(shí)現(xiàn)上述目標(biāo)的代碼。
Figure9GettingAllMembers
publicclassTester
{
publicstaticvoidMain()
{
//檢查一個(gè)單一的對象
TypetheType=Type.GetType("System.Reflection.Assembly");
Console.WriteLine("\nSingleTypeis{0}\n",theType);
//獲取所有的成員
MemberInfo[]mbrInfoArray=
theType.GetMembers(BindingFlags.LookupAll);
foreach(MemberInfombrInfoinmbrInfoArray)
{
Console.WriteLine("{0}isa{1}",
mbrInfo,mbrInfo.MemberType.Format());
}
}
}
盡管得到的輸出還非常長,但在輸出中我們可以得到如下面的不甘落后民示的域、方法、構(gòu)造器和屬性:
System.Strings_localFilePrefixisaField
BooleanIsDefined(System.Type)isaMethod
Void.ctor()isaConstructor
System.StringCodeBaseisaProperty
System.StringCopiedCodeBaseisaProperty
為了對屬性進(jìn)行測試,我們創(chuàng)建一個(gè)名字為MyMath的簡單類,并給它添加二個(gè)函數(shù),然后給它指定bugfix屬性。
[BugFixAttribute(121,"JesseLiberty","01/03/05")]
[BugFixAttribute(107,"JesseLiberty","01/04/05",
Comment="Fixedoffbyoneerrors")]
publicclassMyMath
這些數(shù)據(jù)將與元數(shù)據(jù)存儲在一起。下面是完整的源代碼及其輸出:
自定義屬性
usingSystem;
//創(chuàng)建被指派給類成員的自定義屬性
[AttributeUsage(AttributeTargets.Class,
AllowMultiple=true)]
publicclassBugFixAttribute:System.Attribute
{
//位置參數(shù)的自定義屬性構(gòu)造器
publicBugFixAttribute
(intbugID,
stringprogrammer,
stringdate)
{
this.bugID=bugID;
this.programmer=programmer;
this.date=date;
}
publicintBugID
{
get
{
returnbugID;
}
}
//命名參數(shù)的屬性
publicstringComment
{
get
{
returncomment;
}
set
{
comment=value;
}
}
publicstringDate
{
get
{
returndate;
}
}
publicstringProgrammer
{
get
{
returnprogrammer;
}
}
//專有成員數(shù)據(jù)
privateintbugID;
privatestringcomment;
privatestringdate;
privatestringprogrammer;
}
//把屬性指派給類
[BugFixAttribute(121,"JesseLiberty","01/03/05")]
[BugFixAttribute(107,"JesseLiberty","01/04/05",
Comment="Fixedoffbyoneerrors")]
publicclassMyMath
{
publicdoubleDoFunc1(doubleparam1)
{
returnparam1+DoFunc2(param1);
}
publicdoubleDoFunc2(doubleparam1)
{
returnparam1/3;
}
}
publicclassTester
{
publicstaticvoidMain()
{
MyMathmm=newMyMath();
Console.WriteLine("CallingDoFunc(7).Result:{0}",
mm.DoFunc1(7));
}
}
輸出:
CallingDoFunc(7).Result:9.3333333333333339
象我們看到的那樣,屬性對輸出絕對沒有影響,創(chuàng)建屬性也不會影響代碼的性能。到目前為止,讀者也只是在聽我論述有關(guān)屬性的問題,使用ILDASM瀏覽元數(shù)據(jù),就會發(fā)現(xiàn)屬性確實(shí)是存在的。
映射
在許多情況下,我們需要一種方法,能夠從元數(shù)據(jù)中訪問屬性,C#提供了對映射的支持以訪問元數(shù)據(jù)。通過初始化MemberInfo類型對象,System.Reflection名字空間中的這個(gè)對象可以用來發(fā)現(xiàn)成員的屬性,對元數(shù)據(jù)進(jìn)行訪問。
System.Reflection.MemberInfoinf=typeof(MyMath);
對MyMath類型調(diào)用typeof操作符,它返回一個(gè)由繼承MemberInfo而生成的Type類型的變量。
下一步是對MemberInfo對象調(diào)用GetCustomAttributes,并將希望得到的屬性的類型作為一個(gè)參數(shù)傳遞給GetCustomAttributes??荚嚧筇崾緦⒌玫揭粋€(gè)對象數(shù)組,數(shù)組的每個(gè)成員的類型都是BugFixAttribute。
object[]attributes;
attributes=Attribute.GetCustomAttributes(inf,typeof(BugFixAttribute));我們就可以遍歷這個(gè)數(shù)組了,打印BugFixAttribute對象的數(shù)組,代碼下所示:
屬性的打印
publicstaticvoidMain()
{
MyMathmm=newMyMath();
Console.WriteLine("CallingDoFunc(7).Result:{0}",
mm.DoFunc1(7));
//獲取成員信息并使用它訪問自定義的屬性
System.Reflection.MemberInfoinf=typeof(MyMath);
object[]attributes;
attributes=
Attribute.GetCustomAttributes(inf,typeof(BugFixAttribute));
//遍歷所有的屬性
foreach(Objectattributeinattributes)
{
BugFixAttributebfa=(BugFixAttribute)attribute;
Console.WriteLine("\nBugID:{0}",bfa.BugID);
Console.WriteLine("Programmer:{0}",bfa.Programmer);
Console.WriteLine("Date:{0}",bfa.Date);
Console.WriteLine("Comment:{0}",bfa.Comment);
}
}
類型發(fā)現(xiàn)
我們可以通過映象的方法來研究一個(gè)組合實(shí)體的內(nèi)容,如果要建立需要顯示組合體內(nèi)部信息的工具或動(dòng)態(tài)地調(diào)用組合體中的途徑,這一方法是非常有用的。
通過映象的方法,我們可以知道一個(gè)模塊、方法、域、屬性的類型,以及該類型的每個(gè)方法的信號、該類支持的界面和該類的超級類。我們可以通過如下的形式,用Assembly.Load靜態(tài)方法動(dòng)態(tài)地加載一個(gè)組合體:
publicstaticAssembly.Load(AssemblyName)
然后,可以將它傳遞到核心庫中。
Assemblya=Assembly.Load("Mscorlib.dll");
一旦加載了組合體,我們可以通過調(diào)用GetTypes返回一個(gè)Type對象數(shù)組。Type對象是映射的核心,它表示類、界面、數(shù)組、值和枚舉等的類型定義。
Type[]types=a.GetTypes();
組合休會返回一個(gè)類型的數(shù)組,我們可以使用foreach-loop結(jié)構(gòu)顯示該數(shù)組,其輸出將有好幾頁文檔之多,下面我們從中找一小段:
TypeisSystem.TypeCode
TypeisSystem.Security.Util.StringExpressionSet
TypeisSystem.Text.UTF7Encoding$Encoder
TypeisSystem.ArgIterator
TypeisSystem.Runtime.Remoting.JITLookupTable
1205typesfound
我們得到了一個(gè)內(nèi)容為核心庫中類型的數(shù)組,可以將它們都打印出來,該數(shù)組將有1205個(gè)項(xiàng)。
對一種類型映射我們也可以對組合體中一種類型進(jìn)行映射。為此,我們可以使用GetType方法從組合體中解析出一個(gè)類型:
publicclassTester
{
publicstaticvoidMain()
{
//檢查一個(gè)對象
TypetheType=Type.GetType("System.Reflection.Assembly");
Console.WriteLine("\nSingleTypeis{0}\n",theType);
}
}
輸出如下所示:
SingleTypeisSystem.Reflection.Assembly
發(fā)現(xiàn)成員
我們還可以得到所有成員的類型,顯示所有的方法、屬性、域,下面的代碼演示了實(shí)現(xiàn)上述目標(biāo)的代碼。
Figure9GettingAllMembers
publicclassTester
{
publicstaticvoidMain()
{
//檢查一個(gè)單一的對象
TypetheType=Type.GetType("System.Reflection.Assembly");
Console.WriteLine("\nSingleTypeis{0}\n",theType);
//獲取所有的成員
MemberInfo[]mbrInfoArray=
theType.GetMembers(BindingFlags.LookupAll);
foreach(MemberInfombrInfoinmbrInfoArray)
{
Console.WriteLine("{0}isa{1}",
mbrInfo,mbrInfo.MemberType.Format());
}
}
}
盡管得到的輸出還非常長,但在輸出中我們可以得到如下面的不甘落后民示的域、方法、構(gòu)造器和屬性:
System.Strings_localFilePrefixisaField
BooleanIsDefined(System.Type)isaMethod
Void.ctor()isaConstructor
System.StringCodeBaseisaProperty
System.StringCopiedCodeBaseisaProperty