zoukankan      html  css  js  c++  java
  • WebService中运用自定义类的处理要领(转)

    http://hi.baidu.com/cjhong_520/item/d7d1d595e4c048d91b49dfa9

    最近一个项目要用到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是最传统最好的办法了,呵呵~


  • 相关阅读:
    阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_3 Mybatis中编写dao实现类的使用-修改删除等其他操作
    阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_2 Mybatis中编写dao实现类的使用-保存操作
    阶段3 1.Mybatis_06.使用Mybatis完成DAO层的开发_1 Mybatis中编写dao实现类的使用方式-查询列表
    阶段3 1.Mybatis_05.使用Mybatis完成CRUD_9 Mybatis中的返回值深入-解决实体类属性和数据库列名不对应的两种方式
    阶段3 1.Mybatis_05.使用Mybatis完成CRUD_8 Mybatis中的返回值深入-调整实体类属性解决增和改方法的报错
    阶段3 1.Mybatis_05.使用Mybatis完成CRUD_7 Mybatis中参数的深入-使用实体类的包装对象作为查询条件
    阶段3 1.Mybatis_05.使用Mybatis完成CRUD_6 Mybatis的CRUD-保存操作的细节-获取保存数据的id
    strace命令【转】
    I2S协议
    自动登录脚本
  • 原文地址:https://www.cnblogs.com/zuiyirenjian/p/2725853.html
Copyright © 2011-2022 走看看