Go homepage(回首页) Upload pictures (上传图片) Write articles (发文字帖)
The author:(作者)归海一刀published in(发表于) 2014/1/30 0:52:05 Asp.net,Ajax,学习笔记7,客户端访问WebService(中)_[Asp.Net教程]
1、使用复杂参数或返回值
作为参数的类型一定要有默认的构造函数,就是说要有无参的构造函数。 客户端使用的类型必须要和服务端的类型共有域变量及属性,注:设置的属性必须要有Setter方法。客户端使用服务端的复杂类型有两种方式构造一个对象。1是使用JSon字符串的形势,设置一个变量,让它的值类似与{"名称1":值1, "名称2":值2}这种方式,名称1,名称2,要与服务段公有的字段相同。 var color = {"Red" : 50, "Green" : 100, "Blue" : 200};Red、Green、Blue都与服务段的Color对象的字段名字相同。2是实例化一个对象,对象名为[Namespaces].ClassName(),然后是用如下代码,给对象的字段赋值 var color = new ComplexType.Color();color.Red = 50;color.Green = 100;color.Blue = 200;这叫复杂对象的代理。实例化时只能使用类的无参构造函数。 在客户端和服务段传递对象时自动进行(JSon)序列化与反序列化。 生成复杂对象代理时,需要在服务端使用GenerateScriptType属性标记要代理的类[GenerateScriptType(typeof(Color))]注:此标记可以标记在类、接口以及方法上 如果服务器端类型有基类、派生类等继承关系,当然可以根据具体的情况生成具体的派生类对象,还可以直接实例化一个Object对象,设置这个对象__type属性,在把这个对象传递到服务端时,服务端可根据此标记自动反序列化为一个派生类,这样可以实现一个多态的效果,这个Object对象就是基类的对象,根据__type属性自动实例化一个派生类 2、使用JavaScriptConverter
JavaScriptConverter可以用来处理存在循环引用的类和结果不是开发人员所期望那样的类型,如一个类型没有无参的构造函数,那么是否就不能在客户端使用了?使用JavaScriptConverter就能够在客户端使用使用DataTable这样的复杂类型时,可以使用JavaScriptConverter来解决
这是使用别人已经写好的JavaScriptConverter来使用DataSet,DataRow,DataTable数据类型。
3、自己编写JavaScriptConverter
自定义JavaScriptConverter需要继承JavaScriptConverter对象,并重写Deserialize、Serialize、SupportedTypes方法和属性
namespace Converter{
public class BoyConverter : JavaScriptConverter { //此方法在由客户端的对象向服务段对象进行传递时调用 public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) { //实例化一个Boy对象 Boy boy = new Boy(); //将Boy的Name被设置为dictionary的Name的key的值 boy.Name = (string)dictionary["Name"]; //注意dictionary["GirlFriend"]的值是一个JSon对象,用来保存客户端GirlFriend的对象 //所以需要用JavaScriptSerializer来将此JSon对象转换为一个服务段Gril对象 boy.GirlFriend = serializer.ConvertToType(dictionary["GirlFriend"]); //设置boy的GirlFriend的BoyFirend,在服务端不用担心循环引用的问题 boy.GirlFriend.BoyFriend = boy;
//返回被设置好的Boy对象 return boy; }
//此方法在由服务端对象向客户端对象进行传递是调用 public override IDictionary Serialize(object obj, JavaScriptSerializer serializer) { //转换传递进来的参数为Boy类型 Boy boy = (Boy)obj; //实例化一个字典类型 IDictionary result = new Dictionary();
//设置字典类型的key为Name,值为Boy的Name result["Name"] = boy.Name;
//将boy的GirFriend的BoyFriend引用设置为空,避免在客户端出现循环引用的问题 boy.GirlFriend.BoyFriend = null; //设置字典类型的key为GirlFriend为Boy的GirlFriend result["GirlFriend"] = boy.GirlFriend; //返回IDictionary对象,到客户端被转换为JSon对象,并且,不能使用boy.GirlFriend.BoyFriend //类似的代码 return result; }
public override IEnumerable SupportedTypes { get { //在 foreach 每次循环调用迭代程序的 //MoveNext 方法时,它都从前一次 yield return 语句停止的地方开始执行 yield return typeof(Boy); } } }在实现好JavaScriptConverter类之后,需要在WebConfig里加上指定的Converter标签加载的地方与DataTable类似。Name:转换者的名字,随便起 Type:Converter.BoyConverter转换者的命名空间加类名,App_Code:转换者类文件存放的地址,好像无所谓,我随便填也没出错
4、序列化和反序列化
客户端的反序列化: Sys.Serialization.JavaScriptSerializer.deserialize('<%= this.SerializedDateTime %>');
服务端的序列化 JavaScriptSerializer serializer = new JavaScriptSerializer();serializer.Serialize(DateTime.Now);注意:客户端是静态方法。DateTime序列化后不是一个JSon字符串。 上面是简单类型的序列化和反序列化,如果是复杂的对象类型需要用到JavaScriptTypeResolver自定义一个Resolver类并继承JavaScriptTypeResolver类,重写ResolveType、ResolveTypeId两个方法JavaScriptTypeResolver不是一个直接使用的类,他是用来辅助JavaScriptSerializer类的,作为构造函数的参数传入。 namespace TypeResolver{ /**//// /// Summary description for CustomizeTypeResolver /// public class CustomizeTypeResolver : JavaScriptTypeResolver { //从字符串标识获取一个Type对象 public override Type ResolveType(string id) { //id就是从客户端对象的__type的值 switch (id) { case "0": return typeof(Intern); case "1": return typeof(Vendor); case "2": return typeof(FulltimeEmployee); } return null; } //得到Type对象的标识字符串 public override string ResolveTypeId(Type type) { if (type == typeof(Intern)) { //返回客户端就是__type属性的值 return "0"; } else if (type == typeof(Vendor)) { return "1"; } else if (type == typeof(FulltimeEmployee)) { return "2"; } return null; } }}这是类的定义 Employee emp = null;switch (id){ case 0: emp = new Intern(); break; case 1: emp = new Vendor(); break; default: emp = new FulltimeEmployee(); break;}//用Resolver对象来实例一个JavaScriptSerializer对西那个 JavaScriptSerializer serializer = new JavaScriptSerializer(new CustomizeTypeResolver());//序列化复杂对象return serializer.Serialize(emp);这是使用方法
赞