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>
/// <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>
/// <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是最传统最好的办法了,呵呵~
WebService中使用自定义类的解决方法(5种)的更多相关文章
- 在OpenCV2.2后的版本中没有CvvImage类的解决方法(及出现错误:IntelliSense: 未定义标识符 "CvvImage" )
首先在你的解决方案资源管理器中的头文件和源文件下分别添加 CvvImage.cpp 如下图: view类头上加个#include "CvvImage.h" 头文件,应该就可以解决 ...
- @NamedEntityGraphs --JPA按实体类对象参数中的字段排序问题得解决方法
JPA按实体类对象参数中的字段排序问题得解决方法@Entity @Table(name="complaints") @NamedEntityGraphs({ @NamedEntit ...
- VS2012中丢失ArcGIS模板的解决方法
VS2012中丢失ArcGIS模板的解决方法 由于ArcGIS10.0(for .NET)默认是用VS2010作为开发工具的,所以在先安装VS2012后装ArcGIS10.0 桌面版及ArcObjec ...
- java开发中遇到的问题及解决方法(持续更新)
摘自 http://blog.csdn.net/pony12/article/details/38456261 java开发中遇到的问题及解决方法(持续更新) 工作中,以C/C++开发为主,难免与其他 ...
- android6.0SDK 删除HttpClient的相关类的解决方法
本文转载自博客:http://blog.csdn.net/yangqingqo/article/details/48214865 android6.0SDK中删除HttpClient的相关类的解决方法 ...
- Java Native Interfce三在JNI中使用Java类的普通方法与变量
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 前面我们学习了如何在JNI中通过参数来使用J ...
- Java的cmd配置(也即Java的JDK配置及相关常用命令)——找不到或无法加载主类 的解决方法
Java的cmd配置(也即Java的JDK配置及相关常用命令) ——找不到或无法加载主类 的解决方法 这段时间一直纠结于cmd下Java无法编译运行的问题.主要问题描述如下: javac 命令可以正 ...
- js中style.display=""无效的解决方法
本文实例讲述了js中style.display=""无效的解决方法.分享给大家供大家参考.具体解决方法如下: 一.问题描述: 在js中我们有时想动态的控制一个div显示或隐藏或更多 ...
- SpringBoot拦截器中无法注入bean的解决方法
SpringBoot拦截器中无法注入bean的解决方法 在使用springboot的拦截器时,有时候希望在拦截器中注入bean方便使用 但是如果直接注入会发现无法注入而报空指针异常 解决方法: 在注册 ...
随机推荐
- android黑科技系列——破解游戏之修改金币数
我们在玩游戏的时候总是会遇到一些东东需要进行购买的,但是我们可能又舍不得花钱,那么我们该怎么办呢?那就是用游戏外挂吧!我们这里说的是Android中的游戏,在网上搜索一下移动端游戏外挂,可能会找到一款 ...
- angular.js表单验证
表单验证<AngularJs> 常用的表单验证指令 1. 必填项验证 某个表单输入是否已填写,只要在输入字段元素上添加HTML5标记required即可: <input type=& ...
- jQuery 父级,祖先,兄弟,等选择性操作
jQuery.parent(expr) 找父亲节点,可以传入expr进行过滤,比如$("span").parent()或者$("span").parent(&q ...
- PHP Base64 加密 & 解密
<?php 加密: $cany = 'getshell.top'; #定义要加密的字符串 echo base64_encode($cany); #输出加密后的字符串 解密: $cany = 'Z ...
- JS 封装一个求n~m的求和函数
var a = 0; cc(2,10); function cc(n,m){ for(var i =n;i<(m+1);i++){ a = a + ...
- 路飞学城Python-Day101
57-多表操作之一对多添加纪录 def add(request): # pub = Publish.objects.create(name='人民出版社', email='873245193@qq.c ...
- 找到多个与名为“HOME”的控制器匹配的类型。如果为此请求(“{CONTROLLER}/{ACTION}/{ID}”)提供服务的路由在搜索匹配此请求的控制器时没有指定命名空间,则会发生此情况。如果是这样,请通过调用含有“NAMESPACES”参数的“MAPROUTE”方法的重载来注册此路由。
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/ ...
- 计蒜客 宝藏 (状压DP)
链接 : Here! 思路 : 状压DP. 开始想直接爆搜, T掉了, 然后就采用了状压DP的方法来做. 定义$f[S]$为集合$S$的最小代价, $dis[i]$则记录第$i$个点的"深度 ...
- XPath语法简明介绍
简介: XPath 是一门在 XML 文档中查找信息的语言.XPath 用于在 XML 文档中通过元素和属性进行导航. XPath 路径表达式: XPath 使用路径表达式来选取 XML 文档中的节点 ...
- leetCode笔记--binary tree
993. Cousins in Binary Tree In a binary tree, the root node is at depth 0, and children of each dept ...