1. 程式人生 > >如何在C#.net中自定義和使用特性

如何在C#.net中自定義和使用特性

Attribute的基本概念

經常有周邊人問,Attribute是什麼?它有什麼用?好像沒有這個東東程式也能執行。實際上在.Net中,Attribute是一個非常重要的組成部分,本文整理相關資料,提供給大家參考。

首先,我們肯定Attribute是一個類,下面是msdn文件對它的描述:公共語言執行時允許你新增類似關鍵字的描述宣告,叫做attributes, 它對程式中的元素進行標註,如型別、欄位、方法和屬性等。

Attributes和Microsoft .NET Framework檔案的元資料儲存在一起,可以用來向執行時描述你的程式碼,或者在程式執行的時候影響應用程式的行為。

在.NET中,Attribute被用來處理多種問題,比如序列化、程式的安全特徵、防止即時編譯器對程式程式碼進行優化從而程式碼容易除錯等等。

複雜的,面向元件的業務開發,期待現代的軟體開發工程師們具備更多的彈性設計,而不是過去的方法設計。微軟的.NET框架通過眾所周知的宣告式程式設計,廣泛的使用特性來附加額外的功能。在軟體系統裡,使用特性可以增強系統的彈性,這是因為,特性使功能的低耦合得到了增強。所以,你可以定製自己的特性類,然後根據你自己的意圖,合理的使用這些具有低耦合功效的特性。

使用.NET框架編寫Windows程式,在很多方面已經變得很簡單。在許多情況下,.NET框架使用.NET編譯器,在編譯時繫結到程式集的元資料,使靈活的程式設計變得更容易。事實上,對於.NET而言,使用內嵌的元資料把我們從DLL地獄解脫出來是可能的。

值得慶幸的是,.NET框架的設計者們並沒有選擇把這些元資料優雅的隱藏起來。設計者們把反射API給予了我們,通過反射,一個.NET程式可以通過程式設計檢視這個元資料。一個程式可以反射出包含在特定程式集內任意的東西,或者說是包含在其內的所有的型別和成員。(反射內容待續,請關注)

把元資料繫結到可執行的程式集裡,提供了許多優勢。這使得.NET程式集,完全可以自我描述。還允許開發者跨語言共享元件,去除了標頭檔案的需要。(這些標頭檔案會由於相關的實現程式碼而過期。)

關於.NET元資料所有好的地方,看起來很難讓人相信,它好像沒什麼用,僅僅是個謊言。但是,它確實是存在的。在.NET裡,你可以建立自己特定程式的元資料,並且可以把這些元資料應用到你可以想象到的地方。

開發者通過使用自定義特性,可以定義他們自己特定程式的元資料。因為這些特性的值將變成另一部分元資料,繫結到一個程式集裡。所以這些自定義特性的值可以被反射API檢查到並且可以被使用。

問題:我們經常提到一個類的屬性,這些屬性的值可以作為特性來使用。那麼屬性和自定義特性真正的區別在哪裡呢?

通過這篇文章,你將學會如何定製特性,如何把特性應用到你的原始碼類和方法上,以及如何使用反射API獲取和使用這些特性的值。

公共語言執行時是如何使用特性的?


在你開始考慮如何使用你自己定義的特性類之前,讓我們檢視一些標準的特性,這些已經在公共語言執行時有用到。

[WebMethod]特性提供了一個簡單的例子。它可以使WebService派生的子類中任意公共的方法轉化成Web Service暴露方法的一部分,而這一切,僅僅通過把[WebMethod]附加到方法的定義上就可以做到。

public class SomeWebService : System.Web.Services.WebService
{
[WebMethod]
public DataSet GetDailySales()
{
//處理請求的程式碼
}
}
你只要把[WebMethod]特性新增到一個方法上,.NET就會在後臺為你處理其它所有的事情。

在給定的方法上使用[Conditional]特性,那麼此方法是否可呼叫將取決於指定的預處理識別符號是否被定義。舉個例子,看如下的程式碼:

public class SomeClass
{
[Conditional("DEBUG")]
public void UnitTest()
{
//單元測試程式碼
}
}


這段程式碼說明,該類的方法UnitTest()是否有效,將取決於預處理識別符號“DEBUG”是否被定義(譯註:在編譯除錯版本時,DEBUG常數已經被定義)。我們可能更感興趣的是,使用[Conditional]後真正發生了什麼。當條件失效時,編譯器將會停止所有對該方法的呼叫,相比有同樣功能的預處理指令#if...#endif,此方法顯得更簡潔,而且,使用這項功能,我們不需要多做任何事情。

特性使用了定位引數和命名引數。在使用了[Conditional]特性的例子中,特定的符號就是定位引數。定位引數是強制性的,你必須提供。

讓我們回到使用了[WebMethod]特性的例子,來看一下命名引數。這個特性有一個Description的命名引數,可以像下面這樣使用:

[WebMethod(Description = "Sales volume")]

命名引數是可選擇的,引數的值要緊跟著寫在引數名字的後面。如果存在定位引數,那麼你需要先書寫定位引數,然後在定位引數的後面書寫命名引數。

我將會在文章的後面講述更多關於定位引數和命名引數的內容,這將在我向你展示如何建立和使用你自己的特性類時提到。


特性可用於執行時,設計時


在這篇文章裡,我提供的都是與執行時的行為相關的例子。但是二進位制檔案(程式集)並不只是用於執行時。在.NET裡,你所定義的元資料也不只是侷限於執行時,相反,當你編譯成程式集後,在任何時候你都可以查閱這些元資料。

考慮在設計時,使用元資料的一些可能的情況。在Visual Studio.Net裡,使用IDE可以構建工具(使用.NET語言),方便開發和設計(嚮導,構建器等等)。這樣,一個模組的執行時的環境(如:IDE工具)就成了另一個模組的設計時環境(被開發的原始碼)。這裡提供了一個使用定製特性很好的例子。IDE工具將會反射你編寫的類和型別,然後遵照你的程式碼行事。不幸的是,由於沒有IDE工具的程式碼,探究這樣的例子,已經超出了該文章所闡述的範圍。

標準的.NET特性包含了一個類似的例子。當一個開發者建立自定義控制元件並把它放到Visual Studio.Net IDE的工具箱中,它們(自定義控制元件)已經使用了一系列特性,用於說明在屬性表單中如何處理自定義控制元件。下面列舉並描述了在屬性表單中用到的4種標準的.NET特性。

在Visual Studio .NET IDE裡設計時屬性表單用到的標準的.NET特性:

Attribute Description
Designer 指定用於為元件實現設計時服務的類。
DefaultProperty 指定在屬性表單中,元件的預設的屬性。
Category 指定在屬性表單中,屬性的類別。
Description 指定在屬性表單中,有關屬性的描述。

這些與表單相關的特性,讓我們認識到,可以在設計時使用特性以及它們的值,就像在執行時一樣。


自定義特性類的屬性


在特性和類的屬性之間存在著明顯相似的地方。這給我們何時、何處應該使用自定義特性帶來了困惑。開發者們通常引用一個類的屬性,並把屬性的值作為自己“特性”,那麼屬性和特性之間真正的區別在哪裡呢?

當你定義特性的時候,它和屬性沒有根本的區別,使用時,可以以相同的方式把它附加到程式集不同的型別上,而不僅僅在類上使用。下面列舉了可以應用特性的所有程式集型別。

可以應用特性的所有程式集型別。

Type:Assembly Class Delegate Enum Event Interface Method Module Parameter Constructor

Field Property ReturnValue Structure

讓我們從清單中挑選一個作為例子。你可以在引數上應用特性,這看起來很微小,好像是在給引數新增屬性?其實,這是一個新穎的,非常不錯的主意,因為你不會用類的屬性做這件事。這裡也突出了特性和屬性之間很大的不同之處,因為屬性僅僅是類的一個成員而已。它們不能與一個引數,或者清單中列舉的其他型別關聯起來,當然,這要把類排除在外。

在另外的方面,類的屬性被限制在執行的環境下,而特性卻沒有被限制。通過定義,一個屬性就依賴於特定的類,這個屬性僅僅可以通過類的例項訪問,或者通過該類派生類的例項訪問。另一方面,特性卻可以應用到任何地方。在assembly型別上應用特性,以檢驗是否與自定義特性中的相匹配,這對於assembly型別來說,是最適合的了。在下一部分,我將更多的討論自定義特性類中的ValidOn屬性。在面向元件的開發中,這是非常有用的,因為特性的這個特徵將更加促進鬆耦合。

特性和屬性之間另外的一個不同的地方將涉及到它們各自儲存的值。屬性成員的值是一個例項化的值,在執行時,是可以被改變的。而特性的值,是在設計時(在原始碼裡)設定,然後直接把這些特性的值編譯成元資料儲存到程式集裡。之後,你將不能改變這些特性的值。實際上,你已經把這些特性的值,變成硬編碼的、只讀的資料。

考慮一下,你應用特性的時候。舉個例子,在一個類定義的時候,給其附加了一個特性,那麼該類的每一個例項都會擁有相同的特性值,而不論你例項化該類的多少個例項。你不能把特性附加到一個類的例項上,你只可以在型別/類的定義上應用特性。


建立一個自定義特性類


現在,綜合以上的描述,我們將演示一個更實際的實現過程。讓我們建立一個自定義特性類。該特性會儲存一些關於程式碼修改的跟蹤資訊,在原始碼裡,這些都將作為註釋。在這個例子裡,我們將僅僅記錄一些條目:缺陷id,開發者id,修改的日期,導致缺陷的原因,以及有關修正的註釋。為了保持例子足夠的簡單,我們將關注於如何建立一個自定義特性類(DefectTrackAttribute),而該特性類僅被用於類和方法上。DefectTrackAttribute定義的程式碼如下:

using System;
namespace MyAttributeClasses
{
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,AllowMultiple =true)]
public class DefectTrackAttribute :Attribute
{
private string cDefectID ;
private DateTime dModificationDate ;
private string cDeveloperID ;
private string cDefectOrigin ;
private string cFixComment ;

public DefectTrackAttribute ()
{
}


public DefectTrackAttribute (string lcDefectID, string lcModificationDate,

string lcDeveloperID )
{
this.cDefectID = lcDefectID ;
this.dModificationDate = System.DateTime.Parse( lcModificationDate ) ;
this.cDeveloperID = lcDeveloperID ;
}

public string DefectID
{
get { return cDefectID ; }
}

public string ModificationDate
{
get
{ return dModificationDate.ToShortDateString() ; }
}

public string DeveloperID
{
get { return cDeveloperID ; }
}

public string Origin
{
get { return cDefectOrigin ; }
set { cDefectOrigin = value ; }
}

public string FixComment
{
get { return cFixComment ; }
set { cFixComment = value ; }
}

}
}

如果你之前沒有接觸過特性,那麼你將對下面的程式碼有點陌生。

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,AllowMultiple =true)]

這一行程式碼,把特性[AttributeUsage]附加到特性類的定義上。方括號的語法表明一個特性的構造器被呼叫。所以,特性類也可以擁有它們自己的特性,這看起來可能有點混淆,但是隨著我給你展示可以用特性類來做些什麼,你對它的認識,將會越來越清晰。

[AttributeUsage]特性具有一個定位引數和兩個命名引數。定位引數指定了特性類將被用於何種型別,定位引數的值是列舉AttributeTargets的組合。在我的例子裡,我僅僅把特性類應用在類和方法上,所以通過組合兩個AttributeTargets的值的滿足了我的要求。

[AttributeUsage]特性的第一個命名引數是AllowMultiple,該引數指定了是否可以在同一個型別上應用多次(你所定義的)特性類。預設值是false,即不允許應用多次。但是,根據這個例子的實際情況,你將會在某一型別上不止一次的應用特性(DefectTrackAttribute),所以應該使用[AttributeUsage]的命名引數AllowMultiple,並將其設定為true。這是因為,一個特定的類和方法在其生命週期裡會經歷多次修訂,所以你需要使用[DefectTrackAttribute]特性記錄每一次變化。

[AttributeUsage]特性的第二個命名引數是Inherited,它指定了派生類是否繼承此特性。我使用了此引數的預設的值false。因為我使用的是預設值,所以也就不需要指定該命名引數。為什麼不需要繼承呢?我想獲取原始碼的修改資訊是跟每一個具體的類和方法有關的。如果把Inherited 設為true,那麼開發者將會混淆一個類的[DefectTrackAttribute]特性,無法辨別[DefectTrackAttribute]特性是它自己的還是從父類繼承的。

上面的程式碼展示了特性類(DefectTrackAttribute)的定義。它繼承於System.Attribute,事實上,所有的特性均直接或間接的繼承於System.Attribute。

上面的程式碼裡,還定義了特性的5個私有的欄位,這些欄位均用於儲存與特性相關的值。

在我們特性類中第一個方法是構造器,它是帶有3個引數的簽名。構造器的引數對於特性類而言,就是這個特性的定位引數,這些引數是強制性的。如果你願意,你可以過載構造器,使其可以擁有更多的有關定位引數配置的選擇。

我們的特性類中剩下的部分就是一些公有屬性的宣告,這些屬性與類中的私有欄位相對應。當你查閱元資料的時候,你可以使用這些屬性訪問該特性的值。需要說明的是,對應定位引數的屬性沒有set語句,只有get語句。這就導致了這些屬性是隻讀的,這也與它們是定位引數而不是命名引數的含義相一致。


應用自定義特性


你現在已經知道在C#程式碼裡,在一個型別宣告之前,通過在方括號裡使用特性的名字和引數就可以將其附加到目標型別上。在下面的程式碼裡,把[DefectTrack]特性附加到一對類和一對方法上。

using System ;
using MyAttributeClasses ;

namespace SomeClassesToTest
{
[DefectTrack( "1377", "12/15/2007", "David Tansey" ) ]
[DefectTrack( "1363", "12/12/2007", "Toni Feltman",
Origin = "Coding: Unhandled Exception" ) ]
public class SomeCustomPricingClass
{
public double GetAdjustedPrice( double tnPrice, double tnPctAdjust )
{

return tnPrice + ( tnPrice * tnPctAdjust ) ;

}

[DefectTrack( "1351", "12/10/2007", "David Tansey",
Origin = "Specification: Missing Requirement",
FixComment = "Added PriceIsValid( ) function" )]
public bool PriceIsValid( double tnPrice )
{

return tnPrice > 0.00 && tnPrice < 1000.00 ;

}
}

[DefectTrack( "NEW", "12/12/2007", "Mike Feltman" ) ]
public class AnotherCustomClass
{
string cMyMessageString ;

public AnotherCustomClass( ) { }

[DefectTrack( "1399", "12/17/2007", "David Tansey",
Origin = "Analysis: Missing Requirement" ) ]
public void SetMessage( string lcMessageString )
{

this.cMyMessageString = lcMessageString ;

}
}
}

首先,需要確保你可以訪問之前建立的自定義特性,所以需要新增這樣一行程式碼,如下:

using MyAttributeClasses ;

到此,你就可以使用自定義特性[DefectTrack]裝飾或點綴你的類宣告和方法了。

SomeCustomPricingClass有兩處地方用到了[DefectTrack]特性。第一個[DefectTrack]特性僅僅使用了三個定位引數,而第二個[DefectTrack]特性還包含了一個命名引數Origin的指定。

[DefectTrack( "1377", "12/15/2007", "David Tansey" ) ]
[DefectTrack( "1363", "12/12/2007", "Toni Feltman",
Origin = "Coding: Unhandled Exception" ) ]
public class SomeCustomPricingClass
{ }

PriceIsValid()方法也使用了自定義特性[DefectTrack],並且指定了兩個命名引數Origin和FixComment。上述程式碼包含了[DefectTrack]特性幾個額外的用途,你可以檢測這些特性。

一些讀者可能會感到驚奇,因為對於原始碼修改的資訊可以通過使用註釋這種傳統的做法。.NET已經使用工具,通過在註釋裡使用XML塊,把這些資訊很好的組織起來。

使用自定義特性可以使你達到同樣的效果,它同樣提供了一種可以有效組織的方法,用於記錄和處理這些資訊,並且它還有一個額外的優勢。考慮如下情況,當把原始碼編譯成二進位制程式碼的時候,你是否已經丟失了程式碼的註釋?毫無疑問,註釋已經作為副產品,永遠的從可執行程式碼裡移出。相比之下,特性的值已經變成了元資料的一部分,永遠的繫結到一個程式集裡。在沒有原始碼的情況下,你依然可以訪問這些註釋資訊。另外,在原始碼裡允許特性構造一個與當初在設計時值一樣的例項。


獲取自定義特性的值


到此,儘管你已經在類和方法上應用了自定義屬性,但在實戰中你還沒有真正的看到它。不管你是否附加了特性,看起來好像什麼事情也沒有發生。但事實上,事情已經發生了變化,你完全不用理會我的話,你可以用MSIL反編譯工具,開啟一個包含使用了自定義特性型別的EXE或者DLL檔案。MSIL反編譯工具能使你看到在IL程式碼裡你定義的特性和它的值。

儘管通過反編譯程式集,看到了特性的值,證明了它們的確存在,但是你仍然沒有看到跟它們相關的行為。那麼現在,你就可以使用反射API遍歷一個程式集包含的型別,查詢你自定義的特性,在應用了特性的型別上獲取特性的值。

using System ;
using System.Reflection ;
using MyAttributeClasses ;

public class TestMyAttribute
{
public static void Main( )
{
DisplayDefectTrack( "MyAttributes" ) ;
Console.ReadLine();
}


public static void DisplayDefectTrack( string lcAssembly )
{
Assembly loAssembly = Assembly.Load( lcAssembly ) ;
Type[ ] laTypes = loAssembly.GetTypes( ) ;

foreach( Type loType in laTypes )
{
Console.WriteLine("*======================*" ) ;
Console.WriteLine( "TYPE:\t" + loType.ToString( ) ) ;
Console.WriteLine( "*=====================*" ) ;

object[ ] laAttributes = loType.GetCustomAttributes
(typeof( DefectTrackAttribute ), false ) ;

if( laAttributes.Length > 0 )
Console.WriteLine( "\nMod/Fix Log:" ) ;

foreach( Attribute loAtt in laAttributes )
{
DefectTrackAttribute loDefectTrack = (DefectTrackAttribute)loAtt ;
Console.WriteLine( "----------------------" ) ;
Console.WriteLine( "Defect ID:\t" + loDefectTrack.DefectID ) ;
Console.WriteLine( "Date:\t\t" + loDefectTrack.ModificationDate ) ;
Console.WriteLine( "Developer ID:\t" + loDefectTrack.DeveloperID ) ;
Console.WriteLine( "Origin:\t\t" + loDefectTrack.Origin ) ;
Console.WriteLine( "Comment:\n" + loDefectTrack.FixComment ) ;
}

MethodInfo[ ] laMethods = loType.GetMethods(
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly ) ;

if( laMethods.Length > 0 )
{
Console.WriteLine( "\nMethods: " ) ;
Console.WriteLine( "----------------------" ) ;
}

foreach( MethodInfo loMethod in laMethods )
{
Console.WriteLine( "\n\t" + loMethod.ToString( ) ) ;

object[ ] laMethodAttributes = loMethod.GetCustomAttributes(
typeof( DefectTrackAttribute ), false ) ;

if( laMethodAttributes.Length > 0 )
Console.WriteLine( "\n\t\tMod/Fix Log:" ) ;

foreach( Attribute loAtt in laMethodAttributes )
{
DefectTrackAttribute loDefectTrack = (DefectTrackAttribute)loAtt ;
Console.WriteLine( "\t\t----------------" ) ;
Console.WriteLine( "\t\tDefect ID:\t" + loDefectTrack.DefectID ) ;
Console.WriteLine( "\t\tDeveloper ID:\t" + loDefectTrack.DeveloperID ) ;
Console.WriteLine( "\t\tOrigin:\t\t" + loDefectTrack.Origin ) ;

相關推薦

如何在C#.net定義使用特性

Attribute的基本概念 經常有周邊人問,Attribute是什麼?它有什麼用?好像沒有這個東東程式也能執行。實際上在.Net中,Attribute是一個非常重要的組成部分,本文整理相關資料,提供給大家參考。 首先,我們肯定Attribute是一個類,下面是msd

c#(winform)定義ListItem類方便ComboBox添加Item項

urn left over string his 定義 return box item 1.定義ListItem類 public class ListItem { private string _key = string.Empty;

1 .net定義事件的步驟

sender soc size etc utf nbsp 並且 ram void 1 申明一個自定義的類並且繼承事件的基類 public class ClientSocketModelConnectedEvent:EventArgs { priv

c語言定義常量定義的區別

沒有 int 符號表 cnblogs 格式 nbsp 參數 不同之處 區別   他們有共同的好處就是“一改全改,避免輸入錯誤”哪兩者有不同之處嗎?有的。   主要區別就在於,宏定義是在編譯之前進行的,而const是在編譯階段處理的 宏定義不占用內存單元而const定義的常量

C# Winform定義篩選及帶統計行的Datagridview控制元件

網上分享有很多種自制DGV控制元件,都有不小的缺陷。 沒辦法,按需求自己定製了一個。 一、過濾方面類似於Excel的篩選功能。支援右鍵選單篩選,同時也支援在文字框輸入文字按焦點列進行篩選;  二、統計行我採用的是雙Datagridview方案。在構建控制元件時加入一個Dock為Bottom的子Datagr

C語言巨集定義函式的取捨

原文連結:http://www.embedu.org/Column/Column177.htm 要寫好C語言,漂亮的巨集定義是非常重要的。巨集定義可以幫助我們防止出錯,提高程式碼的可移植性和可讀性等。 在軟體開發過程中,經常有一些常用或者通用的功能或者程式碼段,這些功能既可以寫成函式,也可以

c語言定義了一個函式,在main呼叫時提示找不到識別符號

解決方案一: 把定義的函式放在,main函式之前。 void f() { printf("Hello"); } main() { f(); } 解決方案二: 在main函式之前宣告。 void f(); main() { f

.Net定義類作為Dictionary的key詳解

在定義資料結構時,Dictionary提供了快速查詢資料的功能,另外Dictionary< TKey, TValue >屬於key-value鍵值對資料結構,提供了泛型的靈活性,是資料結構的一個利器,但是目前擁有的string,int,bool

關於C語言減運算子的使用及注意事項

++是自增運算子,是單目運算子,其作用是使單個變數的值增1。它有兩種使用情況: 1)前置:++i,先執行i=i+1,再使用i值; 2)後置:i++,先使用i值,再執行i=i+1。 例如: j=3;k=++j; 執行“k=++j”語句後,k=4,j=4。上述語句等效為: j=

asp.net定義錯誤處理頁面

兩種方法均為全站出錯處理方法一:1、新增Web.config, <system.web></system.web>中新增<customErrors mode="On" defaultRedirect="ApplicationErroy.aspx" ></custo

asp.net定義tooltip的顯示

本文根據網上的一篇文章加工而成的 1.建一個js檔案(tooltip.js) //--初始化變數--var rT=true;//允許影象過渡var bT=true;//允許影象淡入淡出var tw=150;//提示框寬度var endaction=false;//結束動畫 v

使用Velocity(VTL)呼叫定義C# .net 的方法

最近在做一個專案,專案裡面使用了VTL模板,用起來還是很方便,這裡給記錄一下用vtl呼叫.net中自定義的方法,高手就不要往下看了,呵呵. 例如我要在模板中呼叫這樣的一個方法,程式碼如下: 名稱空間:XINLG.Web._codes.manage.site._

C#定義控制元件隱藏基類成員(屬性、方法事件)的方法

       編寫自定義控制元件時,總是繼承C#中提供的Control類,而Control類是C#中所有窗體控制元件的基類,裡面定義了大量的屬性、方法和事件,而很多基類成員在自定義控制元件中可能不需要,因為編寫者會希望在自定義控制元件中隱藏這些成員,避免使用者呼叫這些成員。

c# 定義屬性 有 {get; set} 沒有{get; set} 的區別

取值 public 之前 {} 的區別 一個 自動屬性 至少 定義 屬性:public int age{get;set;}    //自動屬性    public int age{} 這種編譯不通過,get和set至少有一個,分別代表,取值和賦值 變量:public i

如何在ASP.NET Core定義中介軟體讀取Request.BodyResponse.Body的內容?

文章名稱: 如何在ASP.NET Core自定義中介軟體讀取Request.Body和Response.Body的內容? 作者: Lamond Lu 地址: https://www.cnblogs.com/lwqlun/p/10954936.html 原始碼: https://github.com/lamo

淺析在QtWidget定義Model(beginInsertRows()endInsertRows()是空架子,類似於一種信號,用來通知底層)

cti ron 初學者 開發 http 沒有 insert ati 學習 Qt 4推出了一組新的item view類,它們使用model/view結構來管理數據與表示層的關系。這種結構帶來的功能上的分離給了開發人員更大的彈性來定制數據項的表示,它也提供一個標準的model接

C# 基礎知識-08----.NETFileStream 類 StreamReader類 BinaryRead 類

logs -1 cnblogs c# mage amr png .cn 基礎知識 C# 基礎知識-08----.NET中FileStream 類 和 StreamReader類 和 BinaryRead 類

Java 增(++) C語言增的區別

%d 區別 但是 [] .cn cnblogs 微軟雅黑 自增 華麗 在Java、c語言等高級語言中自增和自減的作用基本一致,都是變量自身加一或減一。下面我只對自增進行說明,自減是類似的。 自增運算符(++),有兩種書寫形式,一個是在變量前: ++ num; 另一種

C# .netjson字符串對象之間的轉化方法

tools ade href start 反射 serialize lan serializa serial http://blog.csdn.net/xuexiaodong009/article/details/46998069 json作為作為一種最常用的數據,

jackson定義處理序列化反序列化

public turn ali fast col ast mar 繼承 con http://jackyrong.iteye.com/blog/2005323 ********************************************** 對於一直用gson的