浅析ASP.NET的TypeResolver

开发 后端
本文介绍JavaScriptTypeResolver是一个抽象类,虽然是第一次在Atlas多个Release中出现,但是它并不是一个新鲜事物。

一、客户端的序列化与反序列化能力

在ASP.NET AJAX中,为客户端提供序列化能力的是Sys.Serialization.JavaScriptSerializer类的serialize静态方法。这个方法能够将一个客户端对象序列化成为一个JSON字符串,它的使用方法非常简单。如下:

  1. var jsonStr = Sys.Serialization.JavaScriptSerializer.serialize(obj); 

没有过多可说的内容,可能比较“有特点”的地方就是它对于客户端Date对象的序列化操作。如果我们调用下面的代码,会出现什么结果呢?

  1. var jsonStr = Sys.Serialization.JavaScriptSerializer.serialize(new Date()); 

得到的结果类似于是“"@1162814090119@"”,请注意两边还有双引号。这个是一个ASP.NET AJAX对于Date对象比较特殊的表示方法,如果在某些时候开发人员需要自己来“拼接”字符串时,就需要注意这一点。

给ASP.NET AJAX客户端带来反序列化能力的就是Sys.Serialization.JavaScriptSerializer类的deserialize静态方法。如下:

  1. var obj = Sys.Serialization.JavaScriptSerializer.deserialize(jsonStr);  

它事实上只是简单地调用了 JavaScript内置的eval方法。当然,既然序列化时对于Date对象有特殊的表示方法,在反序列化时,也会考虑到这一点: Sys.Serialization.JavaScriptSerializer类的deserialize静态方法在调用Evail之前,会把 “"@...@"”变成“new Date(...)”的形式,这就是标准的JSON字符串了。

二、JavaScriptTypeResolver与JavaScriptConverter

客户端的序列化和反序列化非常简单,我把它放在这里一并说明更像是为了让内容更加完整。而服务器端的序列化与反序列化就不是那么轻易的了,它涉及到大量的字符串操作,也涉及到一定的自定义能力。这才是这片文章想要着重说明的。

ASP.NET AJAX提供的序列化和反序列化能力都是由Microsoft.Web.Script.Serialization这个命名空间下的类完成的。不过幸运的是,他们大都是内部类,真正能够给开发人员使用的只有JavaScriptSerializer类的数个方法而已。ASP.NET AJAX已经带给我们比较充足的序列化与反序列化的能力,我们只需要掌握它,知道它们是如何工作的,那一般也就足够了。

不过要进入对于这些序列化与反序列化能力的了解,首先需要了解其它的两个类:JavaScriptTypeResolver和JavaScriptConverter。

1、JavaScriptTypeResolver

JavaScriptTypeResolver是一个抽象类,虽然是第一次在Atlas多个Release中出现,但是它并不是一个新鲜事物。它的作用就相当于Atlas CTP中的IJavaScriptSerializeContext接口,甚至可以说只是换了类名和方法名(事实上,从一个接口转变为一个抽象类,这个做法让人摸不着头脑,因为现在的抽象类也不存在任何的实现)。这个类的作用是“将一个字符串,与一个特定的类进行关联,使字符串成为那个特定类的一个标识 ”。这个抽象类存在着两个方法:
1). String ResolveTypeId(Type):得到Type对象的标识字符串。
2). Type ResolveType(String):从字符串标识获取一个Type对象。

可以看出,这两个方法是一对相反的操作。他们会分别运用在序列化于反序列化操作之中。如果对于这个类的作用还不是非常了解的话,那么可以看一下 ASP.NET AJAX中这个抽象类的一个简单实现。那就是 Microsoft.Web.Script.Serialization.SimpleTypeResolver类。它的代码如下:

  1. public sealed class SimpleTypeResolver : JavaScriptTypeResolver  
  2. {  
  3. public override Type ResolveType(string id)  
  4. {  
  5. return Type.GetType(id);  
  6. }  
  7. public override string ResolveTypeId(Type type)  
  8. {  
  9. if (type == null)  
  10. {  
  11. throw new ArgumentNullException("type");  
  12. }  
  13. return type.AssemblyQualifiedName;  
  14. }  

SimpleTypeResolver的作用是将一个类的Assembly Qualified Name与一个类型关联了起来。但是个人认为千万不要使用这个类,如果用了这个类的话,Strong Named Assembly的信息不是都暴露出去了吗?Version,Culture,PublicKeyToken,“一个都不能少”。

2、JavaScriptConverter

JavaScriptConverter类的作用是提供了开发人员自定义序列化与反序列化的能力,这一点对于操作含有循环引用的复杂对象尤其重要。在之前的文章中我分析过这个类,也有过这个类的使用示例。不过这个类在RTM Release中的功能被精简了。它的方法和属性被缩减成了三个:

1). IEnumerable<Type> SupportedTypes:只读属性,返回这个Converter所有能够支持的类。
2). object Deserialize(IDictionary<string, object> 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<string, object> Serialize(object obj, JavaScriptSerializer serializer):这个方法的作用相对纯粹一些,将obj对象转换为一个IDictionary<string, object>对象,在这个方法将结果返回后,ASP.NET AJAX会在这个Dictionary中添加“__type”的值,这样的话,在反序列化时也能够使用当前的JavaScriptConverter来进行相反的操作。


3、使用JavaScriptTypeResolver与JavaScriptConveter

当定义了JavaScriptTypeResolver与JavaScriptConverter后,还需要将其添加进某个JavaScriptSerializer后才能生效。代码大致如下:

  1. // 定义一个JavaScriptTypeResolver实例  
  2. JavaScriptTypeResolver resolver = new MyTypeResolver();  
  3. // 创建一个使用上面Resolver的JavaScriptSerializer  
  4. JavaScriptSerializer serializer = new JavaScriptSerializer(resolver);  
  5. // 创建一个JavaScriptConverter数组  
  6. JavaScriptConverter[] converters = new JavaScriptConverter[] { new MyConverter() };  
  7. // 将Converter关联到Serializer中  
  8. serializer.RegisterConverters(converters);  
  9. // 使用JavaScriptSerializer进行序列化或反序列化操作  
  10. serializer.Serialize(...); 

关于JavaScriptConverter的使用,还需要提一点,就是在web.config文件中可以进行一些配置。如下:

  1. <jsonSerialization> 
  2. <converters> 
  3. <add name="..." type="..." /> 
  4. ...  
  5. </converters> 
  6. </jsonSerialization> 
  7.  

需要注意的是,有些朋友认为在 web.config里进行了JavaScriptConverter配置后,这些Converter就会默认被运用在 JavaScriptSerializer的使用上。但是事实上这些配置的Converter只会被运用在Web Service的访问上,如果新创建了一个JavaScriptSerializer,则需要重新分配,才能使JavaScriptConverter生效。

【编辑推荐】

  1. ASP.NET中的WebRequestExecutor
  2. IIS6的ASP.NET ISAPI请求处理过程
  3. ASP.NET中的备份
  4. 浅谈ASP.NET ISAPI
  5. ASP.NET的IIS ISAPI extension
责任编辑:佚名 来源: IT专家网
相关推荐

2009-07-27 15:34:11

MembershipASP.NET

2009-07-24 13:41:15

ASP.NET AJA

2009-08-05 18:36:12

ASP.NET Che

2009-07-22 18:03:00

ASP.NET ASP

2009-07-31 12:43:59

ASP.NET MVC

2009-08-05 15:50:13

ASP.NET优点

2009-08-10 13:32:15

ASP.NET TimASP.NET组件设计

2009-07-29 14:12:45

ASP.NET tra

2009-08-03 13:38:18

ASP.NET编程模型

2009-07-24 15:47:35

ASP.NET与ASP

2009-07-24 18:02:46

ASP.NET编程

2009-08-05 16:50:09

ASP.NET For

2009-08-04 17:16:16

ASP.NET代码优化

2009-08-05 16:17:29

ASP.NET For

2009-08-05 16:53:14

ASP.NET组件设计

2009-08-03 10:07:20

ASP.NET Ses

2009-08-05 13:16:43

ASP.NET URL

2009-08-10 18:19:37

ASP.NET安装环境

2009-08-10 14:55:43

ASP.NET htt

2009-07-29 09:34:54

IsPostBack属ASP.NET
点赞
收藏

51CTO技术栈公众号