在 WebService 中使用屬性
2024-07-21 02:21:16
供稿:網(wǎng)友
 
在 webservice 中發(fā)布一個(gè)方法很簡(jiǎn)單,只要將你要發(fā)布的方法用 system.web.services.webmethodattribute 屬性類來(lái)標(biāo)識(shí)出就可以了,但是該屬性只能應(yīng)用于方法而不能應(yīng)用到屬性。該類的msdn文檔可以見(jiàn)到(c#):
[attributeusage(attributetargets.method)]
public sealed class webmethodattribute : attribute
  那么,如果我們需要將一個(gè)屬性也發(fā)布成一個(gè)web方法,該如何做呢?在討論這個(gè)問(wèn)題之前,先來(lái)看看為什么我們需要發(fā)布屬性為一個(gè)web方法?因?yàn)橛腥丝赡軙?huì)這么告訴你,你可以把你的屬性改寫(xiě)成兩個(gè)對(duì)應(yīng)的getxxxxx/setxxxxx方法來(lái)分別發(fā)布成webmethod。哦,是的,這么做看似可以達(dá)到目的,但是這樣做損害了我們的接口定義,使得我們無(wú)法享受屬性為我們所帶來(lái)的快樂(lè)(請(qǐng)不要問(wèn)我是什么快樂(lè)),其實(shí)最重要的一個(gè)原因就是無(wú)法完成對(duì)接口的實(shí)現(xiàn)了,此話怎講?且看下面代碼(c#):
public interface idataservice
{
 // 該屬性指示當(dāng)前使用的是什么數(shù)據(jù)庫(kù)系統(tǒng)(例如:ms-sqlserver、orcale、ibm-db2 等等)
 int dataprovider
 {
 get;
 } 
 // 該方法執(zhí)行一段指定的sql腳本,并返回其結(jié)果集
 system.data.dataset execute(string sqltext); 
 // 該方法將指定的數(shù)據(jù)集保存到數(shù)據(jù)庫(kù)中
 void update(system.data.dataset dataset);
} 
  現(xiàn)在我們寫(xiě)一個(gè) webservice 其需要實(shí)現(xiàn) idataservice 接口,必須在該 webservice 中包含并發(fā)布該屬性。這時(shí)我們?cè)撛趺崔k?呵呵,且看
public class dataservice : system.web.services.webserbice, idataservice
{
 ... 
 public int dataprovider
 {
 [webmethod(messagename="getdataprovider")]
 get
 {
 ...
 }
 } 
 [webmethod()]
 public system.data.dataset execute(string sqltext)
 {
 ...
 }
}
  ok,大家看到了,將一個(gè)方法發(fā)布成web方法是在其函數(shù)體前指定 webmethod 屬性,而屬性則是在其get或set器之前指定 webmethod 屬性,如果不指定屬性的 messagename 屬性值,則發(fā)布的屬性的web方法名將被置為get_xxxxx和set_xxxxx。
  在使用vs.net生成的 webservice 代理類(通過(guò)添加web引用,reference.cs)中的成員都是方法,因此需要手動(dòng)修改代理類中的相關(guān)方法為屬性,例如上例的本地代理類的相關(guān)代碼看起來(lái)是這樣的:
[system.web.services.protocols.soapdocumentmethodattribute(... ...)]
[return: system.xml.serialization.xmlelementattribute("getdataproviderresult")]
public int getdataprovider()
{
 object[] results = this.invoke("getdataprovider", new object[0]);
 return (int)results[0];
} 
那么,你只需將該方法的主體部分大概改成這個(gè)樣子即可:
public int getdataprovider
{
 [system.web.services.protocols.soapdocumentmethodattribute(... ...)]
 [return: system.xml.serialization.xmlelementattribute("getdataproviderresult")]
 get
 {
 object[] results = this.invoke("getdataprovider", new object[0]);
 return (int)results[0];
 }
} 
通過(guò)以上步驟就可以在 webservice 中使用屬性了。呵呵,快樂(lè)又重新回來(lái)了!
后話:
  在開(kāi)發(fā)過(guò)程中,你可能需要經(jīng)常發(fā)布新的方法到你的 webservice 頁(yè)面中,客戶端程序也需要同步更新 webservice 以獲得最新的接口,當(dāng)客戶端刷新 webservice 引用后你的代理類就會(huì)丟失你上面所作的修改。你可以維護(hù)一個(gè)客戶端代理類,并將這個(gè)代理類編譯到一個(gè)單獨(dú)的類庫(kù)中,而所有需要引用此 webservice 的客戶端就只需引用該類庫(kù)中的代理類了,這樣可以避免多個(gè)開(kāi)發(fā)人員在每次更新 webservice 引用時(shí)的同步更改問(wèn)題了,并且簡(jiǎn)化了 webservice 的發(fā)布。當(dāng)然,使用這種方式你需要認(rèn)真考慮你的類庫(kù)版本以及命名空間的一些策略,這也是一件相當(dāng)有趣并充滿藝術(shù)性的事情。
  另外,有關(guān) webservice 頁(yè)面大小(包含方法個(gè)數(shù))與性能的問(wèn)題也需要我們給予足夠的關(guān)注,有關(guān)這方面的一個(gè)建議請(qǐng)參考我的這篇日志:http://blog.csdn.net/sw515/archive/2004/07/20/46349.aspx