一、所有Webservice中傳遞的對象都必須能夠序列化,這個是作為在網(wǎng)絡之間傳輸?shù)谋匾獥l件。XML WebService和SOAP標準支持的數(shù)據(jù)類型如下:
1.基本數(shù)據(jù)類型.
標準類型,如:int float bool DateTime string等基本數(shù)據(jù)類型
2.枚舉.
支持枚舉Enum定義的類型
3.自定義對象.
可以傳遞任意基于自定義類或結構創(chuàng)建的對象。 但要注意一點: 它只能傳輸數(shù)據(jù)成員(變量和屬性).
如果定義了方法,則方法不能進行序列化傳輸,序列化后只剩下數(shù)據(jù)成員.
4.DataSet對象
支持DataSet,切記:不支持DataTable和DataRow,DataSet已經(jīng)是XML Webservice能夠支持的最小的可序列化對象.
5.XmlNode對象
基于XmlNode的對象可以表示XML文檔的一部分.
6.數(shù)組和集合
可以使用任何被支持的類型的數(shù)組和簡單集合,包括: DataSet對象/XmlNode對象和自定義對象.
二、webservice傳輸過程中常遇到的問題
(1)在調用WebService并給一個方法傳遞了一個DataRow參數(shù)時,運行時會拋出異常: "沒法將參數(shù)序列化!",如果把DataRow加入到DataSet中,并將DataSet作為參數(shù) 傳遞再運行就OK了。 這是因為:XML WebService只能對數(shù)據(jù)集DataSet對象類型進行XML序列化,不能對DataRow對象類型進行XML序列化造成的錯誤.因此了解一下 XML WebService支持序列化的基本數(shù)據(jù)類型是比較重要的.
?。?)除了上述的基本類型以外,Webservice服務不能完成直接序列化傳輸,但是大部分數(shù)據(jù)結構借助序列化,仍然可以在Webservice上傳輸。
例如:
在將一個自定義類序列化到文件時,出現(xiàn)如下錯誤提示:
System.Reflection.TargetInvocationException: 調用的目標發(fā)生了異常。 --->
System.InvalidOperationException: 生成 XML 文檔時出錯。 ---> System.InvalidOperationException:
不應是類型 Alink.T1System.Windows.PrintSetting。使用 XmlInclude 或 SoapInclude 屬性靜態(tài)指定非已知的類型。
經(jīng)查找資料,發(fā)現(xiàn)當被序例化的類中包含自定義的復雜類時,需要使用XmlIncludeAttribut屬性標識自定義類
現(xiàn)在修改如下:
using System.Xml.Serialization;
[XmlInclude(typeof(自定義類))]
[Serializable]
public class MyDIYClass
自定義的類都添加標記,提供的webservice方法也加標記
[WebMethod]
[XmlInclude(typeof(自定義類))]
public object WebServiceMethod(Object requestObj)
要把該類中內含的自定義類都用XmlInclude一次,就可以解決問題了;
這樣就可以傳輸了,List<>,ArrayList對象都可以傳輸,但是返回類型為ArrayList的[WebMethod]方法,在客戶端調用后,得到的是object數(shù)組,而且object中的 property全部都變?yōu)閒ield。另外,接口也不能序列化例如List<Interface>也是不能序列化的,遇到這種情況可以把接口修改為抽象類,同時在抽象類上添加[XmlInclude]屬 性,最后需要注意一點,自己寫的類要想序列化必須有默認構造函數(shù)(不帶參數(shù)的構造函數(shù))。
三、xml序列化答疑:
(1)需序列化的字段必須是公共的(public)
?。?)需要序列化的類都必須有一個無參的構造函數(shù)
?。?)枚舉變量可序列化為字符串,無需用[XmlInclude]
?。?)導出非基本類型對象,都必須用[XmlInclude]事先聲明。該規(guī)則遞歸作用到子元素
如導出ArrayList對象,若其成員是自定義的,需預包含處理:
using System.Xml.Serialization;
[XmlInclude(typeof(自定義類))]
(5)Attribute中的IsNullable參數(shù)若等于false,表示若元素為null則不顯示該元素。
也就是說:針對值類型(如結構體)該功能是實效的
若數(shù)組包含了100個空間,填充了10個類對象,則序列化后只顯示10個節(jié)點
若數(shù)組包含了100個空間,填充了10個結構體對象,則序列化后會顯示100個節(jié)點
?。?)真正無法XML序列化的情況,某些類就是無法XML序列化的(即使使用了[XmlInclude])
IDictionary(如HashTable)
System.Drawing.Color
System.Drawing.Font
SecurityAttribute聲明
父類對象賦予子類對象值的情況
對象間循環(huán)引用
?。?)對于無法XML序列化的對象,可考慮使用自定義xml序列化(實現(xiàn)IXmlSerializable接口)實現(xiàn)IDictionary的類,可考慮
?。?)用其它集合類替代;(2)用類封裝之,并提供Add和this函數(shù)
(8)某些類型需要先經(jīng)過轉換,然后才能序列化為 XML。如XML序列化System.Drawing.Color,可先用ToArgb()將其轉換為整數(shù),過于復雜的對象用xml序列化不便的 話,可考慮用二進制序列化。
四、webservice序列化和反序列化實例
//序列化為xml的方法
public static string ToXml(this object obj)
{
XmlSerializer serializer = new XmlSerializer(obj.GetType());
StringWriter sw = new StringWriter();
serializer.Serialize(sw, obj);
return sw.ToString();
}
//反序列化為XML的方法
public static T ToObj<T>(string xml) //where T : Object { XmlSerializer serializer = new XmlSerializer(typeof(T)); StringReader sw = new StringReader(xml); object obj = serializer.Deserialize(sw); if (obj is T) { return (T)obj; } else { return default(T); } }
//客戶端調用webservice中的InsertData(string entity)方法,傳遞的是的類實體product_entity,序列化代碼如下:
pm.WebProductService ps = new pm.WebProductService();
Entity.VAERP.Product product_entity = new Entity.VAERP.Product();
string entity = product_entity.ToXml(); string result = ps.InsertData(entity);
//服務端webservice中反序列化,代碼示例如下:
//entity是客戶端傳過來的序列化的參數(shù)
Entity.VAERP.Product product_entity = new Entity.VAERP.Product();
product_entity = ToObj<Entity.VAERP.Product>(entity);