本文标签:TypeConverter ASP.NET
TypeConverter对于编写ASP.NET Server Control的朋友可谓是再熟悉不过了 。我们通过示例,一步一步地来查看如何在Atlas中使用自定义TypeConverter 。
JavaScriptConverter类的作用是提供了开发人员自定义序列化与反序列化的能力,这一点对于操作含有循环引用的复杂对象尤其重要 。这个类在RTM Release中的功能被精简了 。它的方法和属性被缩减成了三个:
1. IEnumerable SupportedTypes:只读属性,返回这个Converter所有能够支持的类 。
2. object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer):
这个方法的第一个参数是一个字典,有朋友可能会认为这个字典和JSON字符串的表示非常的接近:由Dictionary和List嵌套而成,最底端的元素为一些基本类型对象 。不过事实上不是如此 。ASP.NET AJAX在反序列化一个JSON字符串时,如果出现了“{ "__type" : "...", ...}” 这样的片断时,在将其转换为真正的JSON表示的Dictionary(只存在基本类型对象的Dictionary)之后,如果发现该 Dictionary存在“__type”这个Key,那么就会设法在这个时候就将它转换为__type值表示的那个类型了 。也就是说, JavaScriptConverter的Deserialize方法接受到的第一个参数字典中,也有可能已经是一个特殊的类型了 。
第二个参数为转换的目标类型 。而第三个参数,则是调用当前Deserialize方法的JavaScriptSerializer了,我们的一些反序列化操作可以委托给它执行,它已经关联好了web.config中配置的JavaScriptConverter 。不过需要注意的就是,千万要避免下一步操作又没有改变地回到了当前的Deserialize方法,显然这样会出现死循环 。
3. IDictionary Serialize(object obj, JavaScriptSerializer serializer):这个方法的作用相对纯粹一些,将obj对象转换为一个IDictionary对象,在这个方法将结果返回后,ASP.NET AJAX会在这个Dictionary中添加“__type”的值,这样的话,在反序列化时也能够使用当前的JavaScriptConverter来进行相反的操作 。
首先,定义一个复杂类型Employee: - [TypeConverter(typeof(EmployeeConverter))]
- public class Employee
- {
- public string Name;
- public int Age;
- }
可以看到,我们使用了TypeConverterAttribute将稍后会讲解的EmployeeConverter关联到Employee上 。
接着,和上一个例子一样,我们写一个支持HTTP GET访问的Web Services方法,只是参数使用了复杂类型 。 - [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("//Name").InnerText = employee.Name; responseDoc.SelectSingleNode("//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 participationtitle>
- head>
- <body style="font-family:Verdana; font-size:13px;">
- <h4>Heres 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>
上面这些对于看过之前一片文章的朋友们来说应该很熟悉 。接下来,我们就进入正题,定义一个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转换成另一个对象 。接着在覆盖 ConvertFrom方法,将传入的value值转换为一个复杂对象Employee 。这里为了方便,我们把Employee对象在客户端JOSN序列化,然后在服务器端再序列化回来,事实上,这种基础类型到复杂类型的转换,完全可以使用任何方式 。
代码都非常简单,也容易理解,因此我们直接看一下使用代码 。由于代码很少,就将Javascript和HTML一并贴出了: - <html xmlns="http://www.w3.org/1999/xhtml" >
- <head>
- <title>Convert Primitive Object using Customized TypeConvertertitle>
- <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”按钮之后,会调用submitEmployee函数,这个函数根据用户的输入构造一个Employee对象,然后再使用 。以上介绍ASP.NET的TypeConverter 。
|