WebService中使用自定义类的解决方法(5种)
轉自:http://www.cnblogs.com/lxinxuan/archive/2007/05/24/758317.html
? ? ? ?Demo下載:http://files.cnblogs.com/lxinxuan/wa.rar
?????? 最近一個項目要用到webservice調用業務層類,剛開始的時候遇到了一點小麻煩,經過這兩天的總結和實踐,終于總結出幾個比較常見的情況下的解決方法。
??????? 不知道大家是怎么解決,可能太簡單了,所以沒有覺得它是一個問題。反正我在博客園中沒有搜索到相關的帖子。
??????? 說實話,以前并沒有真正開發過涉及webservice的項目,頂多也就是看看msdn,寫點小程序,當時并沒有發現問題,因為傳遞的參數和返回值都是簡單數據類型,所以并沒有發現本文提及的問題——使用自定義類。
?????????所謂自定義類,不知道我有沒有表達清楚,這里指的就是petshop中的Model層實體類了。
???????? 比如以下代碼:
using?System.Collections;
using?System.Collections.Generic;
using?System.Text;
namespace?Model
{
????[Serializable]
????public?class?Student
????{
????????private?string?stuName;
????????public?Student()
????????{?}
????????public?string?StuName
????????{
????????????get?{?return?this.stuName;?}
????????????set?{?this.stuName?=?value;?}
????????}
????}
}
webservice傳遞的內容必須是可序列化的,不管是參數還是返回值。上面定義的實體類Student,在類定義之前標示了[Serializable],指明可序列化的。但當涉及到實體類集合的時候,如果使用IList<Student>來表示,就會抱錯,原因是IList是不可以序列化的,這種情況下,我們就可以使用System.Collections.ObjectModel.Collection<Student>來表示一個實體類集合。這里給出了兩種可能出現的實體類和實體類集合,以下就開始說明各種解決方法:
1、把實體類集合,作為Object[]傳遞。
??????這種情況下,我們必須使用webservice中的實體類,傳遞的是實體類集合對應的Object[]傳遞,WebService中方法的參數類型是ArrayList。
比如WebService中的方法是:
????????[WebMethod]
????????public?string?HelloStus(ArrayList?stuList)
????????{
????????????BLL.Class1?cls?=?new?BLL.Class1();
????????????return?cls.GetName(stuList);
????????}
別漏了[XmlInclude(typeof(Student))]這一行,不然在表現層就引用不到WebService中的實體類了。
這個時候,在表現層添加web引用,表現層中的調用代碼如下:(參考Demo中的button1_Click()方法)
????????///?必須使用webservice中的實體類,傳遞實體類集合,作為Object[]傳遞,WebService中的參數類型是ArrayList,并提供一個將集合轉化為Object[]的公共類
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?button1_Click(object?sender,?EventArgs?e)
????????{
????????????string?str?=?"";
????????????localhost.Student?stuInfo1?=?new?localhost.Student();
????????????stuInfo1.StuName?=?"lxinxuan";
????????????localhost.Student?stuInfo2?=?new?localhost.Student();
????????????stuInfo2.StuName?=?"www.cnblogs.com/lxinxuan";
????????????IList<localhost.Student>?stuList?=?new?List<localhost.Student>();
????????????stuList.Add(stuInfo1);
????????????stuList.Add(stuInfo2);
????????????object[]?array?=?this.ConvertToArray<localhost.Student>(stuList);//這是一個將集合轉換為Objec[]的泛型方法
????????????str?=?ser.HelloStus(array);//傳遞Object[],返回值是StuName的值
????????????MessageBox.Show(str);
????????}
//這是一個將集合轉換為Objec[]的泛型方法
?private?object[]?ConvertToArray<T>(IList<T>?tList)
????????{
????????????object[]?array?=?new?object[tList.Count];
????????????int?i?=?0;
????????????foreach?(T?t?in?tList)
????????????{
????????????????array[i]?=?t;
????????????????i++;
????????????}
????????????return?array;
????????}
2、傳遞單個實體類,使用WebService中的實體類
這種情況下,可以看作是情況1的特例——只有一個元素的數組。
當然,這種情況下我們可以換一種做法——使用WebService中的實體類。
先看webservice中的代碼:
????????[WebMethod]
????????public?string?HelloStu(Student?stuInfo)
????????{
????????????return?stuInfo.StuName;
????????}
同樣必須添加這一行代碼[XmlInclude(typeof(Student))]。
然后調用代碼是:
????????///?傳遞單個實體類,使用WebService中的實體類
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?button2_Click(object?sender,?EventArgs?e)
????????{
????????????string?str?=?"";
????????????localhost.Student?stuInfo1?=?new?localhost.Student();//注意,這里調用了webservice中的實體類,而不是Model中的實體類。否則出錯。
????????????stuInfo1.StuName?=?"lxinxuan";
????????????str?=?ser.HelloStu(stuInfo1);//傳遞webservice中的實體類
????????????MessageBox.Show(str);
????????}
3、傳遞實體類構成的Collection。這是和情況1類似的情形,只是傳遞的類型不一樣。可以對照一下。
這種情況下,必須通過修改Reference.cs的代碼,不過每次更新都要重新修改,而且必須每個類修改,比較麻煩!不推薦使用,這不知道是哪位仁兄想出來的方法,我也是看了人家的做法才總結出來的,不過能去修改Reference.cs的代碼,已經說明鉆研精神了,鼓勵下。
同樣先給出webservice中方法的代碼:
????????public?string?HelloStusByList(Collection<Student>?stuList)//這里參數類型是Collection
????????{
????????????BLL.Class1?cls?=?new?BLL.Class1();
????????????return?cls.GetName(stuList);
????????}
方法的參數是Collection,在添加了webservice之后,Reference.cs中的對應方法的參數變成了student[],數組!!webservice和數組走得真近阿。。。這里將Reference.cs中的方法HelloStusByList的參數類型student[]改為Collection<localhost.Student>,如下所示。
表示層調用代碼:
????????///?傳遞實體類構成的Collection,通過修改Reference.cs的代碼,不過每次更新WebService之后都要重新修改,而且必須每個類修改,麻煩
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?button3_Click(object?sender,?EventArgs?e)
????????{
????????????string?str?=?"";
????????????localhost.Student?stuInfo1?=?new?localhost.Student();
????????????stuInfo1.StuName?=?"lxinxuan";
????????????localhost.Student?stuInfo2?=?new?localhost.Student();
????????????stuInfo2.StuName?=?"www.cnblogs.com/lxinxuan";
????????????Collection<localhost.Student>?stuList?=?new?Collection<localhost.Student>();
????????????stuList.Add(stuInfo1);
????????????stuList.Add(stuInfo2);
????????????str?=?ser.HelloStusByList(stuList);//默認情況下,這里HelloStusByList方法的參數是Student[],通過手動修改為Collection,就可以了
????????????MessageBox.Show(str);
????????}
4、先將實體類集合序列化為表現為xml格式的string,然后在webservice中反序列化成Collection<>(注意:不可以是IList<>),然后再傳遞給業務層對象。
[2007-5-25修改:博友“代碼亂了”提出,可以采用二進制序列化。確實是的,這里的xml序列化和binary序列化都是可以的,只是我為了調試時跟蹤信息方便,才用了xml序列化。這里不再羅列出來。謝謝“代碼亂了”]
????????public?string?HelloStusByCollection(string?sXml)
????????{
????????????BLL.Class1?cls?=?new?BLL.Class1();
????????????Collection<Student>?stuList?=?cls.DeSerializerCollection<Student>(sXml,?typeof(Collection<Student>));//先反序列化為Collection
????????????return?cls.GetName(stuList);
????????}
DeserializerCollection方法代碼如下:
????????///?<summary>????????///?
????????///?</summary>
????????///?<typeparam?name="T"></typeparam>
????????///?<param?name="sXml"></param>
????????///?<param?name="type"></param>
????????///?<returns></returns>
????????public?Collection<T>?DeSerializerCollection<T>(string?sXml,?Type?type)
????????{
????????????XmlReader?reader?=?XmlReader.Create(new?StringReader(sXml));
????????????System.Xml.Serialization.XmlSerializer?serializer?=?new?System.Xml.Serialization.XmlSerializer(type);
???????????
????????????object?obj?=?serializer.Deserialize(reader);
????????????return?(Collection<T>)obj;
????????}
表現層調用代碼如下:
????????///?先將實體類集合序列化為string,然后在webservice中反序列化成Collection<>,然后再傳遞給業務層對象
????????///?</summary>
????????///?<param?name="sender"></param>
????????///?<param?name="e"></param>
????????private?void?button4_Click(object?sender,?EventArgs?e)
????????{
????????????string?str?=?"";
????????????Student?stuInfo1?=?new?Student();
????????????stuInfo1.StuName?=?"lxinxuan";
????????????Student?stuInfo2?=?new?Student();
????????????stuInfo2.StuName?=?"www.cnblogs.com/lxinxuan";
????????????Collection<Student>?stuList?=?new?Collection<Student>();
????????????stuList.Add(stuInfo1);
????????????stuList.Add(stuInfo2);
????????????string?stuString?=?this.Serializer<Collection<Student>>(stuList);//先序列化為xml文件格式的string
????????????str?=?ser.HelloStusByCollection(stuString);
????????????MessageBox.Show(str);
????????}
Serialize方法代碼如下:
///?<summary>????????///?實體類集合序列化為字符串
????????///?</summary>
????????///?<typeparam?name="T"></typeparam>
????????///?<param?name="objToXml"></param>
????????///?<returns></returns>
????????public?string?Serializer<T>(T?objToXml)
????????{
????????????System.IO.StringWriter?writer?=?new?System.IO.StringWriter();
????????????System.Xml.Serialization.XmlSerializer?serializer?=?new?System.Xml.Serialization.XmlSerializer(objToXml.GetType());
????????????serializer.Serialize(writer,?objToXml);
????????????return?writer.GetStringBuilder().ToString();
????????}
5、這種情況就是情況4的特例,序列化一個實體類并傳遞,方法類似,就不寫出來,參見Demo代碼。
大概就是這些了,當然傳遞DataSet是最傳統最好的辦法了,呵呵~
轉載于:https://www.cnblogs.com/sharpest/p/8365479.html
總結
以上是生活随笔為你收集整理的WebService中使用自定义类的解决方法(5种)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个身份证号码验证接口[2]
- 下一篇: Swift实现CoreData存储数据