4.上面的例程中用到了自己编写的SerializationTool类的构造函数,还有使用到了该类下的Sedes()方法。这里便是该文档的重点内容所在。接下来就将这个类的原码在下面的例程中给出,并进行讲解。
/// <summary>
/// Author:Daniel Kwok
/// Date:2006/12/14
/// Description:You can use this class to serialize and deserialize some classes you want.
/// </summary>
public class SerializationTool{
Object oSrc;
Object oDes;
public SerializationTool(){}
/// <summary>
/// Overload constructor
/// </summary>
/// <param name="srcObj">Source object</param>
/// <param name="desObj">Destination object</param>
public SerializationTool(Object srcObj,Object desObj){
this.oSrc = srcObj;
this.oDes = desObj;
}
/// <summary>
/// The function of this method describe
/// serialize object named oSrc into condition.xml
/// and deserialize from condition.xml into object named oDes
/// </summary>
/// <returns>oDes</returns>
public Object Sedes(){
IFormatter formatter = new SoapFormatter();
Stream stream = new FileStream("condition.xml",FileMode.Create,FileAccess.Write,FileShare.None);
formatter.Serialize(stream,this.oSrc);
stream.Close();
stream = new FileStream("condition.xml",FileMode.Open,FileAccess.Read,FileShare.Read);
formatter.Binder= new MyBinder(this.oSrc,this.oDes);
this.oDes = formatter.Deserialize(stream);
stream.Close();
return this.oDes;
}
}
/// <summary>
/// Author:Daniel Kwok
/// Date:2006/12/14
/// Description:This class is a customize binding class extends abstract class named SerializationBinder.
/// </summary>
public class MyBinder:SerializationBinder{
Object oSrc;//Source object
Object oDes;//Destination object
public MyBinder():base(){}
public MyBinder(Object srcClass,Object desClass){
this.oSrc = srcClass;
this.oDes = desClass;
}
public override Type BindToType(string assemblyName,string typeName){
//If it is an instance of class that oSrc belongs to,
//generate one instance of class that oDes belongs to
//by deserialization.
if(typeName == (oSrc.GetType()).FullName)
return oDes.GetType();
Assembly a = Assembly.Load(assemblyName);
return a.GetType(typeName);
}
}
SerializationTool类中重载的构造函数内的两个参数分别是将要进行强制转化的两种数据类型(最初定义的EstimateSearchCondition类和WebService 命名空间下的代理的EstimateSearchCondition类)的实例对象。然后,通过SerializationTool类中的Sedes()方法将两种类型进行序列化和反序列化的操作,这样便可以将两种类型进行转化。由于该方法返回的是一个Object的类型,所以在第3部分中用(HostEstimateService.EstimateSearchCondition)st.Sedes();的方式将其强制转化成了所需要的数据类型。
5.通过上面1~4的例程代码,就可以实现自定义类在WebService中的传输使用了。但除了上述的介绍外,在这里还有几点需要进行说明。在撰写例程4部分的代码时,需要在工程中导入System.Runtime.Serialization.Formatters.Soap组件,这样才可以使用相关的类及方法。此外,还需要提醒大家的一点就是,在客户端改变引用WebService的时候,在客户端工程文件下,会自动产生上面提到的Web References文件夹和该文件夹下面的相关文件,当然这里也就包含Reference.cs文件,那么,每当更新或重新生成对WebService引用的时候,上面提到的需要修改的Reference.cs文件下的自定义类,就会恢复到初始化时的情况,也就是该类的内容为空,这就需要你重新进行3中介绍的对该类的覆盖操作。
哎,终于都发布上来了,本来是想一整篇发布,无奈系统提示说是什么篇幅文字过长,非得让分批来发布。算了闲话不说了,讲到这里,对于自定义类作为参数或者返回值在WebService中进行操作的方法的介绍也就基本结束了。以上内容完全利用业余时间所写,由于时间仓促,如果有哪些地方,介绍的不清楚的话,请大家提出,我会尽力回复,希望大家共同进步。
转自: http://danielkwok224.spaces.live.com/
在刚刚开始使用WebService的过程中,多数人都会遇到一个使用上让人比较难受的地方。WebService作为中间层,为其上层或下层之间传递数据,如果该传递的数据类型不是系统默认可以序列化的类型(如String,int等),即自定义的类不论是以WebService方法的参数还是返回值的形式进行传递的时候,都会失败。传输失败的原因是因为通过WebService进行方法调用的时候,使用标准化的XML消息传递机制,所以不能够像使用本地对象一样,直接传递自定义类的实例对象。
在网上看到了很多提到类似问题的帖子,但多数的回答都只是从原理上进行了阐述和说明,而没有实际的例程,对于接触该方面较少的人,虽然能够从原理上理解,但是头脑中仍然不清楚实际的解决方案,并不能够立刻地找到实际的解决方法。有鉴于此,现在将用如下的例程来说明并解决WebService中如何来使用自定义的类。
开发语言:C#
开发环境:Microsoft Visual Studio .NET 2003
1.先给出要在WebService中传递的自定义的类。如下面例程:
[Serializable]
public class EstimateSearchCondition
{
public EstimateSearchCondition(){
}
private String m_EstimateId;
private String m_EstimateName;
public String M_EstimateId{
get{return m_EstimateId;}
set{m_EstimateId = value;}
}
public String M_EstimateName{
get{return m_EstimateName;}
set{m_EstimateName = value;}
}
}
在这段代码中唯一需要说明的地方,就是在类的开始处用红色标记的[Serializable],这说明该类是需要进行序列化的。在这里再补充说明一点,在定义类的时候,除非确定该类不用进行序列化,可以在定义的时候不必添加该标记,除此之外,在类前添加该标记是比较好的习惯。也就是说,虽然是可选项,但是被认为是好的习惯。
2.下面将给出WebService中的方法的定义,如下面例程:
[WebMethod]
public EstimateListDataSet GetEstimateList(EstimateSearchCondition condition)
{
try{
return new EstimateBLO().GetEstimateList(condition);
}
catch(System.Exception ex){
throw new Exception(ex.Message);
}
}
这里的方法定义也不多说了,new EstimateBLO()是生成WebService调用的业务层的实例。
3.接下来说说如何调用WebService提供的方法,并将自定义类作为参数传入该方法。(当然,作为返回值也是同样的道理。)如下面例程:
public ModelResult GetEstimateList(EstimateSearchCondition condition)
{
try{
HostEstimateService.EstimateSearchCondition con = new HostEstimateService.EstimateSearchCondition();
SerializationTool st = new SerializationTool(condition,con);
con = (HostEstimateService.EstimateSearchCondition)st.Sedes();
this.m_EstimateService = new HostEstimateService.EstimateService();
SerializationTool stl = new SerializationTool(this.m_EstimateService.GetEstimateList(con),this.m_EstimateListDataSet);
this.m_EstimateListDataSet = (EstimateListDataSet)stl.Sedes();
return ModelResult.Success;
}
catch(System.Exception ex){
throw new Exception(ex.Message);
}
}
在上面的例程中,由于WebService调用的时候,会代理生成的在WebService 命名空间下的与EstimateSearchCondition同名的类,所以在调用GetEstimateList方法时直接传入EstimateSearchCondition类的实例的时候,会提示类型不匹配,强制转换也无效。在客户端引用WebService服务的时候,在客户端程序的Web References文件夹下的Reference.cs文件内生成的代理类EstimateSearchCondition的内容是空的。这时需要打开Reference.cs文件,将原来EstimateSearchCondition的类定义拷贝到该文件中,覆盖掉Reference.cs文件中的空代理类EstimateSearchCondition。并在该类的定义上面也加上[Serializable]。