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來解決
<system.web.extensions>
<scripting>
<webServices>
<JSonSerialization>
<converters>
<add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.PrevIEw"/>
<add name="DataRowConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataRowConverter, Microsoft.Web.PrevIEw"/>
<add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.PrevIEw"/>
</converters>
</JSonSerialization>
</webServices>
</scripting>
</system.web.extensions>
這是使用別人已經寫好的JavaScriptConverter來使用DataSet,DataRow,DataTable數據類型。
3、自己編寫JavaScriptConverter
自定義JavascriptConverter需要繼承JavaScriptConverter對象,並重寫Deserialize、Serialize、SupportedTypes方法和屬性
namespace Converter
...{
public class BoyConverter : JavaScriptConverter
...{
//此方法在由客戶端的對象向服務段對象進行傳遞時調用
public override object Deserialize(IDictionary<string, object> 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<Girl>(dictionary["GirlFrIEnd"]);
//設置boy的GirlFrIEnd的BoyFirend,在服務端不用擔心循環引用的問題
boy.GirlFriend.BoyFrIEnd = boy;
//返回被設置好的Boy對象
return boy;
}
//此方法在由服務端對象向客戶端對象進行傳遞是調用
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
...{
//轉換傳遞進來的參數為Boy類型
Boy boy = (Boy)obj;
//實例化一個字典類型
IDictionary<string, object> result = new Dictionary<string, object>();
//設置字典類型的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<Type> SupportedTypes
...{
get
...{
//在 foreach 每次循環調用迭代程序的
//MoveNext 方法時,它都從前一次 yIEld return 語句停止的地方開始執行
yIEld return typeof(Boy);
}
}
}在實現好JavaScriptConverter類之需要在WebConfig裡加上指定的Converter標簽<add name="BoyConverter" type="Converter.BoyConverter, App_Code"/>加載的地方與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>
/// Summary description for CustomizeTypeResolver
/// </summary>
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); 這是使用方法