http://blog.csdn.net/marsmao/archive/2008/12/18/3544078.aspx
所謂自訂類,不知道我有沒有表達清楚,這裡指的就是petshop中的Model層實體類了。
比如以下代碼:
using System;
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中的方法是: [XmlInclude(typeof(Student))]
[WebMethod]
public string HelloStus(ArrayList stuList)
{
BLL.Class1 cls = new BLL.Class1();
return cls.GetName(stuList);
} 別漏了[XmlInclude(typeof(Student))]這一行,不然在表現層就引用不到WebService中的實體類了。
這個時候,在表現層添加web引用,表現層中的調用代碼如下:(參考Demo中的button1_Click()方法)
/// <summary>
/// 必須使用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中的代碼:
[XmlInclude(typeof(Student))]
[WebMethod]
public string HelloStu(Student stuInfo)
{
return stuInfo.StuName;
} 同樣必須添加這一行代碼[XmlInclude(typeof(Student))]。
然後調用代碼是:
/**//// <summary> 網管論壇bbs_bitsCN_com
/// 傳遞單個實體類,使用WebService中的實體類
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{ 中國網管論壇bbs.bitsCN.com
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中方法的代碼:
[WebMethod]
public string HelloStusByList(Collection<Student> stuList)//這裡參數類型是Collection 網管下載dl.bitscn.com
{
BLL.Class1 cls = new BLL.Class1();
return cls.GetName(stuList);
} 方法的參數是Collection,在添加了webservice之後,Reference.cs中的對應方法的參數變成了student[],數組!!webservice和數組走得真近阿。。。這裡將Reference.cs中的方法HelloStusByList的參數類型student[]改為Collection<localhost.Student>,如下所示。
展示層調用代碼:
/**//// <summary>
/// 傳遞實體類構成的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<>),然後再傳遞給業務層對象。
[WebMethod]
public string HelloStusByCollection(string sXml)
{
BLL.Class1 cls = new BLL.Class1();
//先還原序列化為collection
Collection<Student> stuList = cls.DeSerializerCollection<Student>(sXml, typeof(Collection<Student>));
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;
}
表現層調用代碼如下:
/**//// <summary>
/// 先將實體類集合序列化為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是最傳統最好的辦法了,呵呵~