原址: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;
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>
        /// 传递单个实体类,使用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中方法的代码:

[WebMethod]
        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>,如下所示。
表示层调用代码:

/// <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<>),然后再传递给业务层对象。
[2007-5-25修改:博友“代码乱了”提出,可以采用二进制序列化。确实是的,这里的xml序列化和binary序列化都是可以的,只是我为了调试时跟踪信息方便,才用了xml序列化。这里不再罗列出来。谢谢“代码乱了”]

[WebMethod]
        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;
        }

表现层调用代码如下:

/// <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是最传统最好的办法了,呵呵~

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处!
本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/archive/2009/03/27/1423339.html,如需转载请自行联系原作者

【转】WebService中使用自定义类的解决方法(5种)相关推荐

  1. WebService中使用自定义类的解决方法(5种)

    转自:http://www.cnblogs.com/lxinxuan/archive/2007/05/24/758317.html Demo下载:http://files.cnblogs.com/lx ...

  2. WebService中运用自定义类的处理要领(转)

    http://hi.baidu.com/cjhong_520/item/d7d1d595e4c048d91b49dfa9 最近一个项目要用到webservice调用业务层类,刚开始的时候遇到了一点小麻 ...

  3. Linux下Tomcat死活找不到JSP页面中import指定类的解决方法

    如果你没有使用任何的IDE,只是用自己喜欢的文本编辑器写代码,并手动部署到webapps/下的话,经常会遇到 "类 cannot be reloved to a type" 的错误 ...

  4. DELPHI 中的自定义类笔记(一) OBJECT 创建类 不用 CREATE 【转】

    原文:http://www.cnblogs.com/delphi-xe5/articles/3884154.html Delphi 中的自定义类笔记(一) 类的声明 有两种声明办法 一.自定义类的父类 ...

  5. python 中关于无法导入自己写的类。解决方法

    python 中关于无法导入自己写的类.解决方法 参考文章: (1)python 中关于无法导入自己写的类.解决方法 (2)https://www.cnblogs.com/jc-home/p/1209 ...

  6. @NamedEntityGraphs --JPA按实体类对象参数中的字段排序问题得解决方法

    JPA按实体类对象参数中的字段排序问题得解决方法@Entity @Table(name="complaints") @NamedEntityGraphs({ @NamedEntit ...

  7. android百度地图覆盖物异步加载图片,Android 百度地图marker中图片不显示的解决方法(推荐)...

    目的: 根据提供的多个经纬度,显示所在地的marker样式,如下: 问题: 1.发现marker中在线加载的图片无法显示出来: 2.获取多个对象后,却只显示出了一个marker: 以下为官网实现方法: ...

  8. python创建类的实例方法-Python中动态创建类实例的方法

    简介 在Java中我们可以通过反射来根据类名创建类实例,那么在Python我们怎么实现类似功能呢? 其实在Python有一个builtin函数import,我们可以使用这个函数来在运行时动态加载一些模 ...

  9. 使用遇到的问题_聚氯化铝在使用过程中遇到的问题及解决方法

    聚氯化铝在使用过程中遇到的问题及解决方法 随着现在工业的发展改良,现在的工业废水水质的变化幅度大,导致处理方面也有新的问题出现,常见的有聚氯化铝投入水中产生泡沫,药剂堵塞泵等问题. 聚氯化铝投入水中产 ...

最新文章

  1. (三)Sass和Compass--制作精灵图片
  2. 赠书:全球首本VS Code中文书来了,高效编程秘诀全收录!
  3. ASP.NET杂谈-一切都从web.config说起(2)(ConfigSections详解-中)
  4. 神武服务器维护打副本,6月9日神武2维护解读:120级副本奖励次数提升
  5. 关于 Visual stdio 编译报错:error MSB6006: “CL.exe”已退出
  6. 通过pgAgent实现PostgreSQL上的自动作业
  7. db2 快速清除表中所以的数据
  8. 手把手带你走进卷积神经网络!
  9. 【VS2010学习笔记】【异常处理】一(无法启动此程序,因为计算机中丢失libiconv-2.dll)
  10. Java实现简易四则运算器
  11. 道路照明之电缆线路 - 设计笔记
  12. luarocks argparse
  13. 《ElasticSearch技术解析与实战-朱林》
  14. Java动态性——反射机制学习笔记
  15. jsliang 求职系列 - 40 - CSS 移动端
  16. java 读取doc文件_如何在java中读取Doc或Docx文件?
  17. webpack4.x的学习
  18. 81、前后端等上下游岗位配合的思考和参考工作方法,望文知意,约定优于沟通
  19. 雨笋教育技术干货:漏洞分析,Docker CVE-2018-6552
  20. Typecho重大漏洞

热门文章

  1. 技巧再多,不如扎实基础:考研数学打牢地基的4个方法!
  2. 一个定期压缩、删除过期数据的emp脚本
  3. 4.6 加法器的优化
  4. ESP32开发之旅——AS608指纹识别模块
  5. A类、B类、AB类、C类、D类五种功率…
  6. 一种察看asp源代码的思路
  7. 怎样用ASP代码获取网页源代码
  8. 进网站显示无法进入服务器,关于无法进入服务器的解决办法
  9. 深入理解 V8 的 Call Stack
  10. 面向对象 三大特性 五大基本原则