ASP.NET控件開發(fā)基礎(chǔ)之類型轉(zhuǎn)換器淺析
ASP.NET控件開發(fā)基礎(chǔ)之類型轉(zhuǎn)換器1.認(rèn)識(shí)默認(rèn)屬性瀏覽器支持
讓我們?cè)僬J(rèn)識(shí)一下屬性,大家知道每個(gè)屬性都是有類型的,最熟悉就是string,int這些類型了,VS2005屬性瀏覽器對(duì)這些屬性類型進(jìn)行了識(shí)別,
如下例子
(1)table控件的Height屬性,當(dāng)你設(shè)置屬性為字符串時(shí),則提示錯(cuò)誤信息
(2)當(dāng)屬性類型為Color屬性時(shí),屬性瀏覽器為你提供顏色選擇器
(3)當(dāng)屬性類型為枚舉類型時(shí),屬性瀏覽器則支持下拉框選擇
(4)當(dāng)類型是時(shí)間類型,屬性瀏覽器則支持時(shí)間選擇器
通過上面,我們認(rèn)識(shí)到屬性瀏覽器默認(rèn)會(huì)判別屬性類型,當(dāng)屬性值跟屬性類型不符時(shí),則會(huì)提示錯(cuò)誤信息.這里我們還認(rèn)識(shí)到屬性瀏覽器默認(rèn)為一些屬性類型提供了便利
ASP.NET控件開發(fā)基礎(chǔ)之類型轉(zhuǎn)換器2.屬性表現(xiàn)形式的多樣性
在定義控件屬性時(shí),可以直接這樣定義,屬性都為字符串形式
- ﹤asp:TextBox ID="TextBox1" runat="server"
- Height="11" BackColor="Blue"
- ForeColor="#FF8000"﹥測(cè)試﹤/asp:TextBox﹥
用代碼表示則是這樣,在后臺(tái)代碼中定義的屬性類型必須相對(duì)應(yīng),BackColor必須為Color類型,否則則會(huì)出錯(cuò),當(dāng)在頁面呈現(xiàn)時(shí),則以字符串形式呈現(xiàn).
- protected void Page_Load(object sender, EventArgs e)
- //TextBox1.BackColor = "blue";
- TextBox1.BackColor = System.Drawing.Color.Red;
- TextBox1.BackColor = System.Drawing.Color.FromName("blue");
通過上面,我們認(rèn)識(shí)到屬性類型需要轉(zhuǎn)換,這里便要引出我們所要講的話題,類型轉(zhuǎn)換器.
例如,當(dāng)BackColor="Blue" 時(shí),則會(huì)激活一個(gè)類型轉(zhuǎn)換器實(shí)例將字符串值轉(zhuǎn)換成聲明的類型(即將"blue"轉(zhuǎn)換成Color類型,然后賦給BackColor.
.net類庫中的基本類型和許多類型都有與其相關(guān)聯(lián)的類型轉(zhuǎn)換器.
一般常用的類型有String,Int,Boolean,DateTime,Enum等類型,其類型已默認(rèn)與其相對(duì)應(yīng)的類型轉(zhuǎn)換器關(guān)聯(lián)起來.
如
Color類默認(rèn)關(guān)聯(lián)的類型轉(zhuǎn)換器System.Drawing.ColorConverter
FontInto類默認(rèn)關(guān)聯(lián)的類型轉(zhuǎn)換器System.Drawing.FontConverter
類型轉(zhuǎn)換器的基類為System.ComponentModel.TypeConverter,所有的類型轉(zhuǎn)換器都從其派生.
下面我們?cè)賮砜匆粋€(gè)例子,
我們先定義一個(gè)復(fù)雜屬性,用于測(cè)試
示例一
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace CustomComponents
- {
- public class Name
- {
- private string firstName;
- private string lastName;
- public String FirstName
- {
- get
- {
- return firstName;
- }
- set
- {
- firstName = value;
- }
- }
- public String LastName
- {
- get
- {
- return lastName;
- }
- set
- {
- lastName = value;
- }
- }
- }
- }
再看aspx文件
其中我們輸出了Label的幾個(gè)屬性,包括FontInfo這個(gè)復(fù)雜屬性,并且實(shí)例化了上面定義的Name類
- ﹤%@ Page Language="C#" %﹥
- ﹤!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"﹥
- ﹤script runat="server"﹥
- void Page_Load(object sender, EventArgs e)
- {
- myLabel.Font.Bold = true;
- myLabel.Font.Italic = false;
- myLabel.Font.Name = "verdana";
- myLabel.Font.Overline = false;
- myLabel.Font.Size = 10;
- myLabel.Font.Strikeout = false;
- myLabel.Font.Underline = true;
- Response.Write(myLabel.Font + "﹤br﹥");
- Response.Write(Label1.Width);
- Response.Write(Label1.BackColor+"﹤br﹥");
- Response.Write(Label1.ForeColor + "﹤br﹥");
- CustomComponents.Name n = new CustomComponents.Name();
- n.FirstName = "張";
- n.LastName = "三";
- Response.Write(n);
- }
- ﹤/script﹥
- ﹤html xmlns="http://www.w3.org/1999/xhtml" ﹥
- ﹤head id="Head1" runat="server"﹥
- ﹤title﹥FontInfo Example﹤/title﹥
- ﹤/head﹥
- ﹤body﹥
- ﹤form id="form1" runat="server"﹥
- ﹤h3﹥FontInfo Example﹤/h3﹥
- ﹤asp:Label id="myLabel"
- runat="server" ﹥
- ﹤/asp:Label﹥
- ﹤br /﹥
- ﹤br /﹥
- ﹤asp:Label ID="Label1" Width="200px" runat="server"
- BackColor="#FF8080" Text="Label" ForeColor="Red"﹥
- ﹤/asp:Label﹥
- ﹤/form﹥
- ﹤/body﹥
- ﹤/html﹥
下面看看輸出結(jié)果,如下圖
結(jié)果是將FontInfo屬性和Color屬性轉(zhuǎn)換成字符串形式呈現(xiàn),而我們自定義的Name屬性只以其類型呈現(xiàn),并未呈現(xiàn)其子屬性值.
再來看看***點(diǎn)默認(rèn)屬性瀏覽器支持和第五篇我們所定義的一個(gè)復(fù)雜屬性CustomComponents.Address,
CustomComponents.Address屬性同樣存在著這樣的問題,再對(duì)比一下FontInfo屬性在屬性瀏覽器的支持,如下圖
---------------------------------------------------------------------------
復(fù)雜屬性CustomComponents.Address無法編輯,只讀,而且顯示的是其屬性類型.
復(fù)雜屬性Font則默認(rèn)顯示了子其屬性的值(其默認(rèn)只顯示Names值和Size值,且為只讀)
問題來了,我們要根據(jù)需要為自定義屬性實(shí)現(xiàn)類型轉(zhuǎn)換器.
ASP.NET控件開發(fā)基礎(chǔ)之類型轉(zhuǎn)換器3.自定義屬性類型轉(zhuǎn)換器
上面已經(jīng)說明問題所在了,實(shí)現(xiàn)類型轉(zhuǎn)換器,可以將屬性類型和字符串類型之間相互轉(zhuǎn)換.
下面我們就為解決這個(gè)問題而來了解類型轉(zhuǎn)換器,我們還是以第五篇的那個(gè)例子來學(xué)習(xí)
在說第二點(diǎn)屬性表現(xiàn)形式的多樣性的時(shí)候已經(jīng)說過了
類型轉(zhuǎn)換器的基類為System.ComponentModel.TypeConverter,所有的類型轉(zhuǎn)換器都從其派生.
下面以第五篇時(shí)的例子為基礎(chǔ)
我們?yōu)锳ddress實(shí)現(xiàn)了一個(gè)類型轉(zhuǎn)換器,其實(shí)現(xiàn)了復(fù)雜屬性代碼的折疊,如下代碼
- [TypeConverter(typeof(ExpandableObjectConverter))]
- public class Address
- {
- }
System.ComponentModel.ExpandableObjectConverter 類也是從TypeConverter類派生
所以當(dāng)自定義復(fù)雜類型的類型轉(zhuǎn)換器時(shí),則可從ExpandableObjectConverter 類派生
如果你定義的屬性不是復(fù)雜屬性,則可以直接從TypeConverter類派生
(1) 值翻譯的類型轉(zhuǎn)換器
從TypeConverter類派生的自定義類型轉(zhuǎn)換器則需要重寫TypeConverter類幾個(gè)方法,主要目的就是實(shí)現(xiàn)自定義屬性類型與字符串值之間的轉(zhuǎn)換.
你需要了解以下幾個(gè)方法,這里我們就以Address屬性為例子,這樣來解釋以下方法更好理解.
其實(shí)可以理解成一來一去的關(guān)系,Form,To,相互之間的轉(zhuǎn)換,如下代碼:
TypeDescriptor類的方法為靜態(tài)方法,通過GetConverter方法獲取類型轉(zhuǎn)換器
然后通過TypeConverter類的ConvertFromString方法和ConvertToString相互轉(zhuǎn)換類型.
示例二
- public class AddressConverter : ExpandableObjectConverter
- {
- 方法#region 方法
- // 返回值能否將String類型轉(zhuǎn)換為Address類型
- //sourceType表示要轉(zhuǎn)換的類型
- public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
- {
- if (sourceType == typeof(string))
- {
- return true;
- }
- return base.CanConvertFrom(context, sourceType);
- }
- // 返回值能否將Address類型轉(zhuǎn)換為String類型
- //sourceType表示要轉(zhuǎn)換到的類型
- public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
- {
- if (destinationType == typeof(string))
- {
- return true;
- }
- return base.CanConvertTo(context, destinationType);
- }
- //將String類型轉(zhuǎn)換為Address類型
- //value為要轉(zhuǎn)換的類型
- public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture,
- object value)
- {
- if (value == null)
- {
- return new Address();
- }
- if (value is string)
- {
- string s = (string)value;
- if (s.Length == 0)
- {
- return new Address();
- }
- string[] parts = s.Split(culture.TextInfo.ListSeparator[0]);
- if (parts.Length != 4)
- {
- throw new ArgumentException("Invalid Address", "value");
- }
- //返回指定類型轉(zhuǎn)換器
- TypeConverter stringConverter = TypeDescriptor.GetConverter(typeof(string));
- return new Address((string)stringConverter.ConvertFromString(context, culture, parts[0]),
- (string)stringConverter.ConvertFromString(context, culture, parts[1]),
- (string)stringConverter.ConvertFromString(context, culture, parts[2]),
- (string)stringConverter.ConvertFromString(context, culture, parts[3]));
- }
- return base.ConvertFrom(context, culture, value);
- }
- //將Address類型轉(zhuǎn)換為String類型
- //value為要轉(zhuǎn)換的類型
- public override object ConvertTo(
- ITypeDescriptorContext context,
- CultureInfo culture, object value, Type destinationType)
- {
- if (value != null)
- {
- if (!(value is Address))
- {
- throw new ArgumentException(
- "Invalid Address", "value");
- }
- }
- if (destinationType == typeof(string))
- {
- if (value == null)
- {
- return String.Empty;
- }
- Address ad = (Address)value;
- TypeConverter stringConverter = TypeDescriptor.GetConverter(typeof(string));
- return String.Join(culture.TextInfo.ListSeparator,
- new string[] {
- stringConverter.ConvertToString(context, culture, ad.Street),
- stringConverter.ConvertToString(context, culture, ad.City),
- stringConverter.ConvertToString(context, culture, ad.State),
- stringConverter.ConvertToString(context, culture, ad.Zip)
- });
- }
- return base.ConvertTo(context, culture, value,
- destinationType);
- }
- #endregion
- }
自定義好類型轉(zhuǎn)換器后,要與屬性相關(guān)聯(lián)起來
- [TypeConverter(typeof(AddressConverter))]
- public class Address
- {
- public Address()
- :
- this(String.Empty, String.Empty,
- String.Empty, String.Empty)
- { }
- public Address(string street, string city,
- string state, string zip)
- {
- this.street = street;
- this.city = city;
- this.state = state;
- this.zip = zip;
- }
- .......
- }
下面來看下效果,如下圖,屬性編輯器顯示的CustomAddress不再顯示其類型了,已將其轉(zhuǎn)化為字符串形式了,如果你設(shè)置CustomAddress可寫的話,就可以直接編輯CustomAddress屬性,但其只有四個(gè)子屬性,所以當(dāng)大于5個(gè)時(shí)就會(huì)出錯(cuò),且格式也不可以亂改,一般情況下都設(shè)置其只讀.
為了在頁面上顯示這個(gè)CustomAddress屬性,還需要為Address類重寫一下ToString方法,如下代碼
- #region方法
- public override string ToString()
- {
- return ToString(CultureInfo.CurrentCulture);
- }
- public virtual string ToString(CultureInfo culture)
- {
- return TypeDescriptor.GetConverter(typeof(Address)).ConvertToString(null, culture, this);
- }
- #endregion
通過上面重寫ToString方法后,輸出的CustomAddress屬性將不再是其類型,而是以字符串形式呈現(xiàn),以下以
Response.Write方法輸出Custom1.CustomAddress輸出,如下圖
上面講了最基本的值翻譯類型轉(zhuǎn)換器,希望對(duì)大家有幫助
(2)向“屬性”窗口提供標(biāo)準(zhǔn)值列表的類型轉(zhuǎn)換器
像省份這樣的屬性,為了方便用戶填寫,我們往往做成下拉框形式,一個(gè)省份里面又有城市,我們往往列出一部分,如果其中數(shù)據(jù)不符合用戶要求的話,用戶還可以自己輸入,使用類型轉(zhuǎn)換器轉(zhuǎn)換器也可以做到這一點(diǎn).
實(shí)現(xiàn)這一效果你需要重寫以下方法,我們添加一個(gè)屬性喜歡的游戲的名稱
因?yàn)閷傩詾镾tring類型,可以直接從StringConverter 派生
示例三
- public class GameConverter : StringConverter
- {
- //返回此對(duì)象是否支持可以從列表中選取的標(biāo)準(zhǔn)值集
- public override bool GetStandardValuesSupported(
- ITypeDescriptorContext context)
- {
- return true;
- }
- //返回下拉框集合類
- public override StandardValuesCollection
- GetStandardValues(ITypeDescriptorContext context)
- {
- return new StandardValuesCollection(new string[]{"傳奇",
- "魔獸世界",
- "龍與地下城"});
- }
- //標(biāo)準(zhǔn)值的集合是否為獨(dú)占列表
- //默認(rèn)為flase,為true則表示無法修改列表值
- public override bool GetStandardValuesExclusive(
- ITypeDescriptorContext context)
- {
- return false;
- }
- }
然后與相關(guān)屬性關(guān)聯(lián)起來
- [TypeConverter(typeof(GameConverter))]
- [Description("喜歡的游戲")]
- public String Game
- {
- get
- {
- return game;
- }
- set
- {
- game = value;
- }
- }
好了,.下面我們看一下效果,如下圖,你可以選擇下拉框的值,也可以自己手動(dòng)輸入,跟枚舉類型很相似,但枚舉類型無法自己修改值.
這一篇主要介紹了類型轉(zhuǎn)換器的基本使用,希望對(duì)大家有所幫助,在寫的同時(shí)我也學(xué)到了很多,講的比較基礎(chǔ),什么時(shí)候我懂了可以再補(bǔ)充,水平有限呀.這一篇就寫到這里,很高興,我已經(jīng)寫到第9篇了,我會(huì)繼續(xù)寫下去的,也希望大家喜歡.
ASP.NET控件開發(fā)基礎(chǔ)之類型轉(zhuǎn)換器的相關(guān)內(nèi)容就向你介紹到這里,希望對(duì)你了解ASP.NET控件開發(fā)基礎(chǔ)之類型轉(zhuǎn)換器有所幫助。
【編輯推薦】