深入Atlas系列:Web Sevices Access in Atlas(6) - 对于复杂数据类型的支持(下)

简介:
 在上一篇文章中,我们提到了 Atlas在将一个Dictionary转换为一个对象时,会调用对应的IJavaScriptSerializationContext对象的 GetType(string)方法,以获得“真正”的目标对象类型。在Atlas对于Web Services方法的Request所引起的转换过程中,这个IJavaScriptSerializationContext对象是一个 WebServiceData类的实例,它的GetType方法会在对应的那个Web Services类中寻找相关的数据类型。那么Atlas是如何寻找这些类型的呢?什么样的类型会被查找到呢?

  通过查看代码,我们可 以发现,WebServiceData.GetType(string)方法其实是返回它的一个叫做_clientTypesDictionary的实例 变量中保存的Type。WebServiceData._clientTypesDictionary在第一被使用之前会被初始化。我们在这里略过了各个 方法之间的调用,直接查看真正初始化该变量的方法:WebServiceData.ProcessClientTypes方法。代码如下:
 ProcessClientTypes()方法分析

  代码很容易理解,通过枚举每一个方法的每一个参数加以处理,最后还要处理返回值类型。在这里有一个相当重要的方法,就是通过ProcessClientType(Type, bool)加载可识别的参数类型,我们来看一下它的代码:
 ProcessClientType(Type, bool)方法分析

  标记完可以处理的类型后,还会递归的将该类型相关的所有类型做处理。例如数组的元素和属性的类型。值得注意的是,在递归处理该类型相关的类型时,只会处理具有set方法的属性,而不会处理公有实例成员变量的类型,这也就解释了在之前的文章《 深入Atlas系列:Web Sevices Access in Atlas(4) - 对于复杂数据类型的支持(上) 》 中问题4所遇到的类型无法找到的错误。奇怪的是,在反序列化的对象之后恢复对象信息时也为实例的成员变量设值,因此个人认为,这是Atlas的一个“失 误”。因此对于作为实例成员变量的类型,除非它也直接作为Web Services方法参数出现过,否则就无法被找到了。但是个人建议,在为Atlas创建Web Services方法的参数类型时,尽量完全使用属性,而不是成员变量。

  不过这样的话,仅仅只有Web Services方法参数,以及相关的类型才能在反序列化的时候被使用到,这样似乎也够用了。不过Atlas的能力还远不止这些。Atlas能够将任意的 类型附加在Web Services类中,使该类型能够在反序列化过程中被找到。这就是ProcessXmlIncludeAttributes方法的功能,可以看到,它在 ProcessClientType()方法中被调用了。我们来看一下它的代码:
 ProcessXmlIncludeAttributes方法分析

  代码非常简单,就不多加解释了。可以看出,原本用来辅助XmlSerialiaer的XmlIncludeAttribute被用在这里了! 这的确是一个好消息,于是我们就能通过为一个方法标记XmlIncludeAttribute来为一个Web Services添加额外支持的数据类型,例如:
[XmlInclude( typeof (AdditionalType))]

  有了这个功能,就为Atlas访问Web Services方法的功能增色了不少。在以后将会有相关示例来演示XmlIncludeAttribute的有用之处。



   到上面为止,从客户端序列化一个对象,到服务器端将Web Services方法的参数生成的整个过程已经讨论完了,也就是说Atlas访问Web Services方法的大部分的实现方式已经分析结束了。下面的做法自然是使用反射机制调用Web Services方法,然后再将所得的结果对象进行JSON序列化输出(Xml序列化输出非常常见,因此在这里不作讨论)。将结果序列化的功能是调用 Microsoft.Web.Script.Serialization.JavaScriptObjectSerializer的静态方法 Serialize(object,IJavaScriptSerializationContext)工作的,不过真正进行序列化工作的是 Microsoft.Web.Script.Serialization.JavaScriptObjectSerializer类的实例方法 SerializeValue。很自然,在构造JavaScriptObjectSerializer的时候传入的 IJavaScriptSerializationContext对象为当前的WebServiceData。我们来看一下SerializeValue 方法的实现:
 SerializeValue方法分析

  如果我们在Web.config里配置了与该类型对应的JavaScriptConverter(详细信息请见之前的文章《 深入Atlas系列:Web Sevices Access in Atlas(5) - 对于复杂数据类型的支持(中) 》), 那么就会调用相应JavaScriptConverter对象的SerializeObject方法进行对象的序列化操作,这就是之前谈到的自定义对象序 列化和反序列化功能的体现。在之后的文章里我将提供相应的示例来具体解释如何通过继承JavaScriptConverter来对Atlas进行扩展,在 某些时候这样的扩展还是相当有必要的,特别是在使用复杂类型的时候。

  在这里,我们只关注Atlas提供的内部序列化对象的方法。因此来看一下SerializeValueInternal方法的实现。代码如下:
 SerializeValueInternal方法

  企图对于如此清晰的代码作任何过多的解释似乎都是愚蠢的行为。需要注意的地方似乎只有在序列化中会对循环的引用进行侦测,如果发现已经被序列 化过的代码又需要序列化了则会抛出InvalidOperationException。不过对于复杂对象,这个似乎是无法避免的,在之后的文章里我将提 供示例来说明如何使用继承JavaScriptConveter来提供对于复杂类型的自定义序列化以及反序列化的方式,正如Atlas中为 DataSet,DataTable和DataRow定义这种扩展一样。

  在上面这个方法中,SerializeDictionary和SerializeEnumerable的实现都非常简单,只是将对象序列化成JSON形式的“{}”或“{}”而已。我们在这里只关注SerializeCustomObject方法的实现,代码如下:
 SerializeCustomObject方法分析

  通过代码可以看到,在序列化一个对象时对略过使用了XmlIgnoreAttribute标记的成员变量或属性,在开发时可以利用这一点。其余的似乎都没有什么可说的了。



   就这样,Atlas调用Web Service方法对于复杂类型支持的代码就全部分析完了。代码可能虽然有点多,但是其逻辑还是相当清晰的,也提供了非常强大的自定义方式以供扩展。在这 篇文章之后,我将会提供几个示例来说明“深入Atlas系列:Web Sevices Access in Atlas(6) - 对于复杂数据类型的支持”三篇文章里所提到的功能,希望对大家有用。另外,如果有朋友看了这些文章有任何感想和使用技巧的话,欢迎和我进行讨论,本人不胜 感激。:)


本文转自 jeffz 51CTO博客,原文链接:http://blog.51cto.com/jeffz/60800,如需转载请自行联系原作者

相关文章
|
JSON JavaScript Go
Go 语言学习指南:变量、循环、函数、数据类型、Web 框架等全面解析
掌握 Go 语言的常见概念,如变量、循环、条件语句、函数、数据类型等等。深入了解 Go 基础知识的好起点是查阅 Go 官方文档
1082 2
|
前端开发 JavaScript
Web 前端大揭秘!JS 数据类型检测竟如此震撼,一场惊心动魄的代码探秘之旅等你来!
【8月更文挑战第23天】在Web前端开发中,合理检测数据类型至关重要。JavaScript作为动态类型语言,变量类型可在运行时变化,因此掌握检测技巧十分必要。
139 1
|
存储 前端开发 JavaScript
Web前端的奇幻之旅:探索JS数据类型的奥秘与差异
【8月更文挑战第23天】JavaScript是一种动态类型语言,提供多种内置数据类型支持信息的存储与操作。这些类型对Web前端开发者至关重要,直接影响代码性能与可读性。JavaScript数据类型主要分为两大类:原始数据类型(如Undefined、Null、Boolean等)与引用数据类型(如Object、Array等)。原始类型直接存储值,而引用类型存储指向数据的引用。原始类型不可变且存储在栈中,访问更快;引用类型则存储在堆中,可通过其引用进行修改。理解这些差异有助于编写高效、可维护的代码。
127 0
|
应用服务中间件
idea 调试报错 Illegal access: this web application instance has been stopped already.
idea 调试报错 Illegal access: this web application instance has been stopped already.
434 0
|
JavaScript 前端开发 开发者
【Web 前端】TypeScript 的内置数据类型有哪些?
【5月更文挑战第1天】【Web 前端】TypeScript 的内置数据类型有哪些?
|
存储 前端开发 JavaScript
【Web 前端】JS数据类型有哪些?区别?
【4月更文挑战第22天】【Web 前端】JS数据类型有哪些?区别?
|
JavaScript 前端开发
【Web 前端】JS中检测数据类型的有哪些?
【4月更文挑战第22天】【Web 前端】JS中检测数据类型的有哪些?
|
应用服务中间件 数据安全/隐私保护
Tomcat【部署 02】Web端403 Access Denied You are not authorized to view this page解决方法(Tomcat 10.2.12 版本)
Tomcat【部署 02】Web端403 Access Denied You are not authorized to view this page解决方法(Tomcat 10.2.12 版本)
1245 0
|
XML JSON 前端开发
ajax中get和post的区别,datatype返回的数据类型有哪些?web开发中数据提交的几种方式,有什么区别。百度使用哪种方式?
ajax中get和post的区别,datatype返回的数据类型有哪些?web开发中数据提交的几种方式,有什么区别。百度使用哪种方式?
182 0