ASP.NET的TypeConverter
TypeConverter對于編寫ASP.NET Server Control的朋友可謂是再熟悉不過了。我們通過示例,一步一步地來查看如何在Atlas中使用自定義TypeConverter。
JavaScriptConverter類的作用是提供了開發(fā)人員自定義序列化與反序列化的能力,這一點對于操作含有循環(huán)引用的復雜對象尤其重要。這個類在RTM Release中的功能被精簡了。它的方法和屬性被縮減成了三個:
1. IEnumerable<Type> SupportedTypes:只讀屬性,返回這個Converter所有能夠支持的類。
2. object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer):
這個方法的***個參數(shù)是一個字典,有朋友可能會認為這個字典和JSON字符串的表示非常的接近:由Dictionary和List嵌套而成,***端的元素為一些基本類型對象。不過事實上不是如此。ASP.NET AJAX在反序列化一個JSON字符串時,如果出現(xiàn)了“{ "__type" : "...", ...}” 這樣的片斷時,在將其轉(zhuǎn)換為真正的JSON表示的Dictionary(只存在基本類型對象的Dictionary)之后,如果發(fā)現(xiàn)該 Dictionary存在“__type”這個Key,那么就會設(shè)法在這個時候就將它轉(zhuǎn)換為__type值表示的那個類型了。也就是說, JavaScriptConverter的Deserialize方法接受到的***個參數(shù)字典中,也有可能已經(jīng)是一個特殊的類型了。
第二個參數(shù)為轉(zhuǎn)換的目標類型。而第三個參數(shù),則是調(diào)用當前Deserialize方法的JavaScriptSerializer了,我們的一些反序列化操作可以委托給它執(zhí)行,它已經(jīng)關(guān)聯(lián)好了web.config中配置的JavaScriptConverter。不過需要注意的就是,千萬要避免下一步操作又沒有改變地回到了當前的Deserialize方法,顯然這樣會出現(xiàn)死循環(huán)。
3. IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer):這個方法的作用相對純粹一些,將obj對象轉(zhuǎn)換為一個IDictionary<string, object>對象,在這個方法將結(jié)果返回后,ASP.NET AJAX會在這個Dictionary中添加“__type”的值,這樣的話,在反序列化時也能夠使用當前的JavaScriptConverter來進行相反的操作。
首先,定義一個復雜類型Employee:
- [TypeConverter(typeof(EmployeeConverter))]
- public class Employee
- {
- public string Name;
- public int Age;
- }
可以看到,我們使用了TypeConverterAttribute將稍后會講解的EmployeeConverter關(guān)聯(lián)到Employee上。
接著,和上一個例子一樣,我們寫一個支持HTTP GET訪問的Web Services方法,只是參數(shù)使用了復雜類型。
- [WebService(Namespace = "http://tempuri.org/")]
- [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
- public class HttpGetEmployeeService : System.Web.Services.WebService {
- [WebMethod]
- [WebOperation(true, ResponseFormatMode.Xml)]
- public XmlDocument SubmitEmployee(Employee employee)
- {
- XmlDocument responseDoc = new XmlDocument();
- responseDoc.LoadXml(
- "<?xml-stylesheet type=\"text/xsl\" href=\"Employee.xsl\"?>" +
- "<Employee><Name></Name><Age></Age></Employee>");
- responseDoc.SelectSingleNode("http://Name").InnerText = employee.Name;
- responseDoc.SelectSingleNode("http://Age").InnerText = employee.Age.ToString();
- return responseDoc;
- }
- }
然后是所需的Xslt文件:
- <?xml version="1.0" encoding="utf-8"?>
- <xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:template match="/Employee">
- <html>
- <head>
- <title>Thanks for your participation</title>
- </head>
- <body style="font-family:Verdana; font-size:13px;">
- <h4>Here's the employee you submitted:</h4>
- <div>
- <xsl:text>Name: </xsl:text>
- <xsl:value-of select="Name" />
- </div>
- <div>
- <xsl:text>Age: </xsl:text>
- <xsl:value-of select="Age" />
- </div>
- </body>
- </html>
- </xsl:template>
- </xsl:stylesheet>
上面這些對于看過之前一片文章的朋友們來說應(yīng)該很熟悉。接下來,我們就進入正題,定義一個EmployeeConverter。代碼如下:
- public class EmployeeConverter : TypeConverter
- {
- public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
- {
- if (sourceType == typeof(String))
- {
- return true;
- }
- return false;
- }
- public override object ConvertFrom(ITypeDescriptorContext context,
CultureInfo culture, object value)- {
- IDictionary<string, object> dictObj =
- JavaScriptObjectDeserializer.DeserializeDictionary(value.ToString());
- Employee emp = new Employee();
- emp.Name = dictObj["Name"].ToString();
- emp.Age = (int)dictObj["Age"];
- return emp;
- }
- }
EmployeeConverter繼承了TypeConverter,首先覆蓋CanConvertFrom方法表明使用EmployeeConverter可以將一個String轉(zhuǎn)換成另一個對象。接著在覆蓋 ConvertFrom方法,將傳入的value值轉(zhuǎn)換為一個復雜對象Employee。這里為了方便,我們把Employee對象在客戶端JOSN序列化,然后在服務(wù)器端再序列化回來,事實上,這種基礎(chǔ)類型到復雜類型的轉(zhuǎn)換,完全可以使用任何方式。
代碼都非常簡單,也容易理解,因此我們直接看一下使用代碼。由于代碼很少,就將Javascript和HTML一并貼出了:
- <html xmlns="http://www.w3.org/1999/xhtml" >
- <head>
- <title>Convert Primitive Object using Customized TypeConverter</title>
- <script language="javascript">
- function submitEmployee()
- {
- var emp = new Object();
- emp.Name = $("txtName").value;
- emp.Age = parseInt($("txtAge").value, 10);
- var serializedEmp = Sys.Serialization.JSON.serialize(emp);
- var url = "HttpGetEmployeeService.asmx?mn=SubmitEmployee&employee=" +
encodeURI(serializedEmp);- window.open(url);
- }
- </script>
- </head>
- <body style="font-family:Verdana; font-size:13px;">
- <form runat="server">
- <atlas:ScriptManager ID="ScriptManager1" runat="server" />
- <div>Name:<input type="text" id="txtName" /></div>
- <div>Age:<input type="text" id="txtAge" /></div>
- <input type="button" value="Submit" onclick="submitEmployee();" />
- </form>
- </body>
- </html>
在奠基“Submit”按鈕之后,會調(diào)用submitEmployee函數(shù),這個函數(shù)根據(jù)用戶的輸入構(gòu)造一個Employee對象,然后再使用。以上介紹ASP.NET的TypeConverter。
【編輯推薦】