博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebService中使用自定义类的解决方法(5种)
阅读量:4609 次
发布时间:2019-06-09

本文共 6337 字,大约阅读时间需要 21 分钟。

        Demo下载:
       最近一个项目要用到webservice调用业务层类,刚开始的时候遇到了一点小麻烦,经过这两天的总结和实践,终于总结出几个比较常见的情况下的解决方法。
        不知道大家是怎么解决,可能太简单了,所以没有觉得它是一个问题。反正我在博客园中没有搜索到相关的帖子。
        说实话,以前并没有真正开发过涉及webservice的项目,顶多也就是看看msdn,写点小程序,当时并没有发现问题,因为传递的参数和返回值都是简单数据类型,所以并没有发现本文提及的问题——使用自定义类。
         所谓自定义类,不知道我有没有表达清楚,这里指的就是petshop中的Model层实体类了。
         比如以下代码:
None.gif
using
 System;
None.gif
using
 System.Collections;
None.gif
using
 System.Collections.Generic;
None.gif
using
 System.Text;
None.gif
None.gif
namespace
 Model
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
{
InBlock.gif    [Serializable]
InBlock.gif    
public class Student
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private string stuName;
InBlock.gif
InBlock.gif        
public Student()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{ }
InBlock.gif
InBlock.gif        
public string StuName
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this.stuName; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis.stuName = value; }
ExpandedSubBlockEnd.gif        }
ExpandedSubBlockEnd.gif    }
InBlock.gif
ExpandedBlockEnd.gif}
None.gif
webservice传递的内容必须是可序列化的,不管是参数还是返回值。上面定义的实体类Student,在类定义之前标示了 [Serializable],指明可序列化的。但当涉及到实体类集合的时候,如果使用IList<Student>来表示,就会抱错,原因是IList是不可以序列化的,这种情况下,我们就可以使用System.Collections.ObjectModel.Collection<Student>来表示一个实体类集合。这里给出了两种可能出现的实体类和实体类集合,以下就开始说明各种解决方法:
1、把实体类集合,作为Object[]传递。
      
这种情况下,我们必须使用webservice中的实体类,传递的是实体类集合对应的Object[]传递,WebService中方法的参数类型是ArrayList。
比如WebService中的方法是:
None.gif
[XmlInclude(
typeof
(Student))]
None.gif        [WebMethod]
None.gif        
public
 
string
 HelloStus(ArrayList stuList)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            BLL.Class1 cls 
= new BLL.Class1();
InBlock.gif            
return cls.GetName(stuList);
ExpandedBlockEnd.gif        }
别漏了
[XmlInclude(
typeof
(Student))]这一行,不然在表现层就引用不到WebService中的实体类了。
这个时候,在表现层添加web引用,表现层中的调用代码如下:(参考Demo中的button1_Click()方法)
ExpandedBlockStart.gif
ContractedBlock.gif
/**/
/// <summary>
InBlock.gif        
/// 必须使用webservice中的实体类,传递实体类集合,作为Object[]传递,WebService中的参数类型是ArrayList,并提供一个将集合转化为Object[]的公共类
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sender"></param>
ExpandedBlockEnd.gif        
/// <param name="e"></param>
None.gif
        
private
 
void
 button1_Click(
object
 sender, EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            
string str = "";
InBlock.gif
InBlock.gif            localhost.Student stuInfo1 
= new localhost.Student();
InBlock.gif            stuInfo1.StuName 
= "lxinxuan";
InBlock.gif            localhost.Student stuInfo2 
= new localhost.Student();
InBlock.gif            stuInfo2.StuName 
= "www.cnblogs.com/lxinxuan";
InBlock.gif
InBlock.gif            IList
<localhost.Student> stuList = new List<localhost.Student>();
InBlock.gif            stuList.Add(stuInfo1);
InBlock.gif            stuList.Add(stuInfo2);
InBlock.gif
InBlock.gif            
object[] array = this.ConvertToArray<localhost.Student>(stuList);//这是一个将集合转换为Objec[]的泛型方法
InBlock.gif
            str = ser.HelloStus(array);//传递Object[],返回值是StuName的值
InBlock.gif
InBlock.gif            MessageBox.Show(str);
ExpandedBlockEnd.gif        }
None.gif
//
这是一个将集合转换为Objec[]的泛型方法
None.gif
 
private
 
object
[] ConvertToArray
<
T
>
(IList
<
T
>
 tList)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            
object[] array = new object[tList.Count];
InBlock.gif            
int i = 0;
InBlock.gif            
foreach (T t in tList)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                array[i] 
= t;
InBlock.gif                i
++;
ExpandedSubBlockEnd.gif            }
InBlock.gif            
return array;
ExpandedBlockEnd.gif        }
None.gif
2、
传递单个实体类,使用WebService中的实体类
这种情况下,可以看作是情况1的特例——只有一个元素的数组。
当然,这种情况下我们可以换一种做法——使用WebService中的实体类。
先看webservice中的代码:
None.gif
[XmlInclude(
typeof
(Student))]
None.gif        [WebMethod]
None.gif        
public
 
string
 HelloStu(Student stuInfo)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            
return stuInfo.StuName;
ExpandedBlockEnd.gif        }
同样必须添加这一行代码
[XmlInclude(
typeof
(Student))]。
然后调用代码是:
ExpandedBlockStart.gif
ContractedBlock.gif
 
/**/
/// <summary>
InBlock.gif        
/// 传递单个实体类,使用WebService中的实体类
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sender"></param>
ExpandedBlockEnd.gif        
/// <param name="e"></param>
None.gif
        
private
 
void
 button2_Click(
object
 sender, EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            
string str = "";InBlock.gif
InBlock.gif            localhost.Student stuInfo1 
= new localhost.Student();//注意,这里调用了webservice中的实体类,而不是Model中的实体类。否则出错。
InBlock.gif            stuInfo1.StuName 
= "lxinxuan";InBlock.gif
InBlock.gif            str 
= ser.HelloStu(stuInfo1);InBlock.gif//传递webservice中的实体类
InBlock.gif            MessageBox.Show(str);
ExpandedBlockEnd.gif        }
3、
传递实体类构成的Collection。这是和情况1类似的情形,只是传递的类型不一样。可以对照一下。
这种情况下,必须通过修改Reference.cs的代码,不过每次更新都要重新修改,而且必须每个类修改,比较麻烦!不推荐使用,这不知道是哪位仁兄想出来的方法,我也是看了人家的做法才总结出来的,不过能去修改Reference.cs的代码,已经说明钻研精神了,鼓励下。
同样先给出webservice中方法的代码:
None.gif
[WebMethod]
None.gif        
public
 
string
 HelloStusByList(Collection
<
Student
>
 stuList)
//
这里参数类型是Collection
ExpandedBlockStart.gifContractedBlock.gif
        
dot.gif
{
InBlock.gif            BLL.Class1 cls 
= new BLL.Class1();
InBlock.gif            
return cls.GetName(stuList);
ExpandedBlockEnd.gif        }
方法的参数是Collection,在添加了webservice之后,Reference.cs中的对应方法的参数变成了student[],数组!!webservice和数组走得真近阿。。。这里将Reference.cs中的方法HelloStusByList的参数类型student[]改为Collection
<
localhost.Student
>,如下所示。
表示层调用代码:
ExpandedBlockStart.gif
ContractedBlock.gif
/**/
/// <summary>
InBlock.gif        
/// 传递实体类构成的Collection,通过修改Reference.cs的代码,不过每次更新WebService之后都要重新修改,而且必须每个类修改,麻烦
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sender"></param>
ExpandedBlockEnd.gif        
/// <param name="e"></param>
None.gif
        
private
 
void
 button3_Click(
object
 sender, EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            
string str = "";
InBlock.gif
InBlock.gif            localhost.Student stuInfo1 
= new localhost.Student();
InBlock.gif            stuInfo1.StuName 
= "lxinxuan";
InBlock.gif            localhost.Student stuInfo2 
= new localhost.Student();
InBlock.gif            stuInfo2.StuName 
= "www.cnblogs.com/lxinxuan";
InBlock.gif
InBlock.gif            Collection
<localhost.Student> stuList = new Collection<localhost.Student>();
InBlock.gif            stuList.Add(stuInfo1);
InBlock.gif            stuList.Add(stuInfo2);
InBlock.gif
InBlock.gif            str 
= ser.HelloStusByList(stuList);//默认情况下,这里HelloStusByList方法的参数是Student[],通过手动修改为Collection,就可以了
InBlock.gif
InBlock.gif            MessageBox.Show(str);
ExpandedBlockEnd.gif        }
4、先将实体类集合序列化为表现为xml格式的string,然后在webservice中反序列化成Collection<>(注意:不可以是IList<>),然后再传递给业务层对象。
[2007-5-25修改:博友“代码乱了”提出,可以采用二进制序列化。确实是的,这里的xml序列化和binary序列化都是可以的,只是我为了调试时跟踪信息方便,才用了xml序列化。这里不再罗列出来。谢谢“代码乱了”]
None.gif
[WebMethod]
None.gif        
public
 
string
 HelloStusByCollection(
string
 sXml)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            BLL.Class1 cls 
= new BLL.Class1();
InBlock.gif            Collection
<Student> stuList = cls.DeSerializerCollection<Student>(sXml, typeof(Collection<Student>));//先反序列化为Collection
InBlock.gif            
return cls.GetName(stuList);
ExpandedBlockEnd.gif        }
DeserializerCollection方法代码如下:
ExpandedBlockStart.gifContractedBlock.gif        
/**/
/// <summary>
InBlock.gif        
/// 
InBlock.gif        
/// </summary>
InBlock.gif        
/// <typeparam name="T"></typeparam>
InBlock.gif        
/// <param name="sXml"></param>
InBlock.gif        
/// <param name="type"></param>
ExpandedBlockEnd.gif        
/// <returns></returns>
None.gif
        
public
 Collection
<
T
>
 DeSerializerCollection
<
T
>
(
string
 sXml, Type type)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            XmlReader reader 
= XmlReader.Create(new StringReader(sXml));
InBlock.gif            System.Xml.Serialization.XmlSerializer serializer 
= new System.Xml.Serialization.XmlSerializer(type);
InBlock.gif           
InBlock.gif            
object obj = serializer.Deserialize(reader);
InBlock.gif            
return (Collection<T>)obj;
ExpandedBlockEnd.gif        }
表现层调用代码如下:
ExpandedBlockStart.gif
ContractedBlock.gif
/**/
/// <summary>
InBlock.gif        
/// 先将实体类集合序列化为string,然后在webservice中反序列化成Collection<>,然后再传递给业务层对象
InBlock.gif        
/// </summary>
InBlock.gif        
/// <param name="sender"></param>
ExpandedBlockEnd.gif        
/// <param name="e"></param>
None.gif
        
private
 
void
 button4_Click(
object
 sender, EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            
string str = "";
InBlock.gif
InBlock.gif            Student stuInfo1 
= new Student();
InBlock.gif            stuInfo1.StuName 
= "lxinxuan";
InBlock.gif            Student stuInfo2 
= new Student();
InBlock.gif            stuInfo2.StuName 
= "www.cnblogs.com/lxinxuan";
InBlock.gif
InBlock.gif            Collection
<Student> stuList = new Collection<Student>();
InBlock.gif            stuList.Add(stuInfo1);
InBlock.gif            stuList.Add(stuInfo2);
InBlock.gif
InBlock.gif            
string stuString = this.Serializer<Collection<Student>>(stuList);//先序列化为xml文件格式的string
InBlock.gif            str 
= ser.HelloStusByCollection(stuString);
InBlock.gif            MessageBox.Show(str);
ExpandedBlockEnd.gif        }
Serialize方法代码如下:
ExpandedBlockStart.gif
ContractedBlock.gif
/**/
/// <summary>
InBlock.gif        
/// 实体类集合序列化为字符串
InBlock.gif        
/// </summary>
InBlock.gif        
/// <typeparam name="T"></typeparam>
InBlock.gif        
/// <param name="objToXml"></param>
ExpandedBlockEnd.gif        
/// <returns></returns>
None.gif
        
public
 
string
 Serializer
<
T
>
(T objToXml)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{
InBlock.gif            System.IO.StringWriter writer 
= new System.IO.StringWriter();
InBlock.gif            System.Xml.Serialization.XmlSerializer serializer 
= new System.Xml.Serialization.XmlSerializer(objToXml.GetType());
InBlock.gif            serializer.Serialize(writer, objToXml);
InBlock.gif            
return writer.GetStringBuilder().ToString();
ExpandedBlockEnd.gif        }
5、这种情况就是情况4的特例,序列化一个实体类并传递,方法类似,就不写出来,参见Demo代码。
大概就是这些了,当然传递DataSet是最传统最好的办法了,呵呵~

转载于:https://www.cnblogs.com/lxinxuan/archive/2007/05/24/758317.html

你可能感兴趣的文章