国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
InfoQ: 實(shí)現(xiàn)Web Service依賴倒置

實(shí)現(xiàn)Web Service依賴倒置

作者 譯者 王翔 發(fā)布于 2007年8月1日 下午10時(shí)49分

社區(qū)
.NET
主題
設(shè)計(jì),
Web服務(wù)

問(wèn)題的提出

作為面向?qū)ο笤O(shè)計(jì)的一個(gè)基本原則,依賴倒置原則(DIP)在降低模塊間耦合度方面有很好的指導(dǎo)意義,他的基本要求和示意圖如下:

“高層模塊不應(yīng)該依賴于低層模塊,二者都應(yīng)該依賴于抽象。抽象不應(yīng)該依賴于細(xì)節(jié)。細(xì)節(jié)應(yīng)該依賴于抽象。”

圖1:直接依賴(I)和依賴關(guān)系倒置(II)

這么做有什么優(yōu)勢(shì)呢?

  • 降低Client與ConcreteService的耦合度。
  • ConcreteService可以自主的變化,只要符合IService,就可以繼續(xù)被Client使用。即這種變化對(duì)Client透明。
  • 應(yīng)用框架可以Client的上下文為他物色一個(gè)合適的ConcreteService,動(dòng)態(tài)構(gòu)造、動(dòng)態(tài)綁定、運(yùn)行時(shí)動(dòng)態(tài)調(diào)用。

在單應(yīng)用時(shí)代,基于接口的開(kāi)發(fā)指導(dǎo)了我們養(yǎng)成這種習(xí)慣,但是到了SOA環(huán)境下,通常的Web Service開(kāi)發(fā)情況又是怎么樣呢?

  1. 客戶程序需要調(diào)用某個(gè)Web Service,獲得它的WSDL和相關(guān)數(shù)據(jù)結(jié)構(gòu)的XSD。
  2. 然后客戶程序調(diào)用這個(gè)Web Service,一般情況下如果WSDL不變的話,可以一直使用該Web Service,即便那個(gè)Web Service后面的實(shí)現(xiàn)平臺(tái)發(fā)生變化,但因?yàn)榻壎P(guān)系沒(méi)有變化,所以客戶程序不需要任何修改(偶爾因?yàn)榘姹締?wèn)題,有可能會(huì)進(jìn)行適應(yīng)性調(diào)整)。
  3. 如果發(fā)現(xiàn)有新的相同服務(wù)接口的Service Provider做的不錯(cuò)的化或者把原有Web Service做遷移的話,那就需要重新更新WSDL,編譯新的Web Service Client Proxy類,有可能客戶程序也要重新編譯。

Web Service很好地隔絕了服務(wù)定義與服務(wù)實(shí)現(xiàn)兩者的關(guān)系,同時(shí)它也把可能的備選功能提供者從內(nèi)部一下子推到整個(gè)互聯(lián)網(wǎng)環(huán)境下,怎么讓客戶程序透明的適應(yīng)眾多可選服務(wù)就成了一個(gè)挑戰(zhàn)。

怎么辦?老辦法——抽象。

實(shí)現(xiàn)Web Service依賴倒置

分析

相信在實(shí)踐設(shè)計(jì)模式的過(guò)程中,開(kāi)發(fā)人員已經(jīng)對(duì)依賴倒置的概念有了深刻的體驗(yàn),“不依賴于具體實(shí)現(xiàn),而是依賴于抽象”,整理SOA環(huán)境下的Web Service一樣需要借鑒這個(gè)概念,筆者將之稱為“Web Service依賴倒置”。大概邏輯結(jié)構(gòu)變成如下:

圖2:概要Web Service依賴倒置后的邏輯關(guān)系

但Web Service本身接口是“平的”,沒(méi)有辦法繼承,只有用OO語(yǔ)言把它進(jìn)行包裝之后才可以成為對(duì)應(yīng)的類,這時(shí)候才能有所謂的“繼承”或“接口實(shí)現(xiàn)”;所謂“抽象”既可能是接口也可能是抽象類(當(dāng)然,也可以考慮用實(shí)體基類),所以在處理ConcreteWebService與抽象Web Service的時(shí)候也有兩種方式:

  • 通過(guò)繼承的
  • 通過(guò)單繼承+多接口組合的

筆者更傾向于后者,因?yàn)橥ㄟ^(guò)組合可以不斷擴(kuò)展。同時(shí)考慮到Web Service使用往往在一個(gè)分布式的環(huán)境中,因此參考RPC中常用的叫法,增加了一一個(gè)Stub(用接口IServiceX表示)和Proxy。修改后依賴倒置的關(guān)系如下:

圖3:分布式環(huán)境下多組合服務(wù)接口實(shí)現(xiàn)的Web Service依賴倒置

實(shí)現(xiàn)示例

1、對(duì)業(yè)務(wù)數(shù)據(jù)建模(XSD):

假設(shè)業(yè)務(wù)對(duì)象為報(bào)價(jià)信息,報(bào)價(jià)分為報(bào)價(jià)頭和明細(xì)(1:0..n),因此結(jié)構(gòu)如下:

圖4:報(bào)價(jià)信息的XSD

XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
  xmlns="http://www.visionlogic.com/trade"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.visionlogic.com/trade"
  elementFormDefault="qualified"
  attributeFormDefault="unqualified">
    <xs:element name="Quote">
        <xs:annotation>
            <xs:documentation>Comment describing your root element</xs:documentation>
        </xs:annotation>
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="QuoteItem" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="Id" type="xs:string" use="required"/>
            <xs:attribute name="Company" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="QuoteItem">
        <xs:complexType>
            <xs:attribute name="ProductId" type="xs:integer" use="required"/>
            <xs:attribute name="Price" type="xs:double" use="required"/>
            <xs:attribute name="QuantitiveInStock" type="xs:double"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

2、完成XSD與對(duì)象實(shí)體的映射:(XSD to Object)

Command

通過(guò)Visual Studio.Net自帶的Xsd.exe進(jìn)行如下操作。


xsd Quote.xsd /c /n:DemoService

這樣就生成了結(jié)構(gòu)大概如下的對(duì)應(yīng)的報(bào)價(jià)實(shí)體類:

C#
using System;
using System.Xml.Serialization;
namespace DemoService
{
    [System.SerializableAttribute()]
    [XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.visionlogic.com/trade")]
    [XmlRootAttribute(Namespace = "http://www.visionlogic.com/trade", IsNullable = false)]
    public partial class Quote
    {
        private QuoteItem[] quoteItemField;
        private string idField;
        private string companyField;
        [XmlElementAttribute("QuoteItem")]
        public QuoteItem[] QuoteItem
        {
            get { return this.quoteItemField; }
            set { this.quoteItemField = value; }
        }
        [XmlAttributeAttribute()]
        public string Id
        {
            get { return this.idField; }
            set { this.idField = value; }
        }
        [XmlAttributeAttribute()]
        public string Company
        {
            get { return this.companyField; }
            set { this.companyField = value; }
        }
    }

    [SerializableAttribute()]
    [XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.visionlogic.com/trade")]
    [XmlRootAttribute(Namespace = "http://www.visionlogic.com/trade", IsNullable = false)]
    public partial class QuoteItem
{
… …
    }
}

3、接著,完成抽象的Web Service定義(optional):

該步驟的目的是獲取wsdl定義。這里筆者為了省事,用Visual Studio.Net自動(dòng)生成,所以寫了個(gè)抽象的Web Service類,實(shí)際開(kāi)發(fā)中完全可以獨(dú)立編寫wsdl文件。

C#
using System.Web.Services;
using System.Xml.Serialization;
namespace DemoService
{
    [WebService(Name="QuoteService", Namespace="http://www.visionlogic.com/trade")]
    public abstract class QuoteServiceBase : WebService
    {
        [WebMethod()]
        [return:XmlElement("Quote", Namespace="http://www.visoinlogic.com/trade")]
        public abstract Quote GetQuote(string id);
    }
}
WSDL (Quote.wsdl)
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.visionlogic.com/trade" xmlns:s1="http://www.visoinlogic.com/trade" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.visionlogic.com/trade" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://www.visionlogic.com/trade">
      <s:import namespace="http://www.visoinlogic.com/trade" />
      <s:element name="GetQuote">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="id" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="GetQuoteResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" ref="s1:Quote" />
          </s:sequence>
        </s:complexType>
      </s:element>
… …
  <wsdl:service name="QuoteService">
    <wsdl:port name="QuoteServiceSoap" binding="tns:QuoteServiceSoap">
      <soap:address location="http://localhost:2401/QuoteServiceBase.asmx" />
    </wsdl:port>
    <wsdl:port name="QuoteServiceSoap12" binding="tns:QuoteServiceSoap12">
      <soap12:address location="http://localhost:2401/QuoteServiceBase.asmx" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

4、生成Web Service接口類型:

Command

通過(guò)Visual Studio.Net自帶的Wsdl.exe進(jìn)行如下操作。


wsdl /n:DemoService /serverinterface /o:IQuoteStub.cs Quote.wsdl Quote.xsd

這樣就生成了報(bào)價(jià)Web Service的抽象接口:

C#
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using System.Xml.Serialization;
namespace DemoService
{
    [WebServiceBindingAttribute(
        Name = "QuoteServiceSoap", Namespace = "http://www.visionlogic.com/trade")]
    public interface IQuoteServiceSoap
    {
        [WebMethodAttribute()]
        [SoapDocumentMethodAttribute(
            "http://www.visionlogic.com/trade/GetQuote",
            RequestNamespace = "http://www.visionlogic.com/trade",
            ResponseNamespace = "http://www.visionlogic.com/trade",
            Use = SoapBindingUse.Literal,
            ParameterStyle = SoapParameterStyle.Wrapped)]
        [return: XmlElementAttribute("Quote",
            Namespace = "http://www.visoinlogic.com/trade")]
        Quote GetQuote(string id);
    }
}

5、生成具體的報(bào)價(jià)Web Service:

為了示例的方便,IntranetQuoteService自己“手捏”了一票測(cè)試報(bào)價(jià)數(shù)據(jù),至此服務(wù)端Web Service工作基本完成,如果需要使用UDDI則還需要把這個(gè)具體服務(wù)publish出來(lái)。

C#
using System;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace DemoService
{
    /// <summary>
    /// 具體的報(bào)價(jià)Web Service 功能實(shí)現(xiàn)
    /// </summary>
    [WebService(Namespace = "http://www.visionlogic.com/trade")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class IntranetQuoteService : WebService, IQuoteServiceSoap
    {
        /// <summary>
        /// 實(shí)現(xiàn)抽象的Web Service調(diào)用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [WebMethod]
        public Quote GetQuote(string id)
        {
            #region "手捏"出來(lái)的測(cè)試數(shù)據(jù)
            Quote quote = new Quote();
            quote.Id = id;
            quote.Company = "deluxe";

            QuoteItem[] items = new QuoteItem[2];
            items[0] = new QuoteItem();
            items[0].QuantitiveInStockSpecified = true;
            items[0].ProductId = "Note Bulletin";
            items[0].Price = 220;
            items[0].QuantitiveInStock = 10;
            items[1] = new QuoteItem();
            items[1].QuantitiveInStockSpecified = true;
            items[1].ProductId = "Pen";
            items[1].Price = 3.4;
            items[1].QuantitiveInStock = 3000;
            quote.QuoteItem = items;
            #endregion

            return quote;
        }
    }
}

6、生成客戶端Proxy:

Command

通過(guò)Visual Studio.Net自帶的Wsdl.exe進(jìn)行如下操作。


wsdl /n:Test.Client /o:QuoteProxy.cs Quote.wsdl Quote.xsd

這樣就生成了報(bào)價(jià)Web Service的客戶端Proxy,他僅通過(guò)最初抽象Web Service的WSDL調(diào)用服務(wù)端Web Service。實(shí)際運(yùn)行過(guò)程中,它并不了解真正使用的時(shí)候是由哪個(gè)服務(wù)提供WSDL中聲明到的“GetQuote”方法。

C#
using System.Web.Services;
using System.Threading;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using System.Xml.Serialization;
using DemoService;
namespace Test.Client
{
    /// <summary>
    /// Web Service 的客戶端 Proxy
    /// </summary>
    [WebServiceBindingAttribute(
        Name="QuoteServiceSoap",
        Namespace="http://www.visionlogic.com/trade")]
    public class QuoteService : SoapHttpClientProtocol
    {   
        /// <summary>
        /// 借助 SOAP 消息調(diào)用 Web Service 服務(wù)端
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [SoapDocumentMethodAttribute(
            "http://www.visionlogic.com/trade/GetQuote",
            RequestNamespace="http://www.visionlogic.com/trade",
            ResponseNamespace="http://www.visionlogic.com/trade",
            Use=SoapBindingUse.Literal,
            ParameterStyle=SoapParameterStyle.Wrapped)]
        [return: XmlElementAttribute("Quote",
            Namespace="http://www.visoinlogic.com/trade")]
        public Quote GetQuote(string id)
        {
            object[] results = this.Invoke("GetQuote", new object[] {id});
            return ((Quote)(results[0]));
        }
    }
}

7、客戶程序:

最后,通過(guò)單元測(cè)試工具檢查的客戶程序如下:

C#
using System;
using DemoService;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test.Client
{
    /// <summary>
    /// 測(cè)試用客戶程序
    /// </summary>
    [TestClass]
    public class Client
    {
        /// <summary>
        /// 為了簡(jiǎn)化,這里在客戶程序中直接定義了具體報(bào)價(jià)Web Service的Uri.
        /// 實(shí)際開(kāi)發(fā)中該信息應(yīng)該作為服務(wù)端的一個(gè)配置項(xiàng)登記在Directory之中,
        /// 客戶程序僅僅通過(guò)抽象的服務(wù)邏輯名稱從Directory中獲得。)
        /// </summary>
        [TestMethod]
        public void Test()
        {
            QuoteService service = new QuoteService();
            service.Url = "http://localhost:2401/IntranetQuoteService.asmx";
            Quote quote = service.GetQuote("quote:2007-07-15");
            Assert.AreEqual<string>("quote:2007-07-15", quote.Id);
            Assert.AreEqual<string>("deluxe", quote.Company);
            Assert.AreEqual<int>(2, quote.QuoteItem.Length);
            Assert.IsNotNull(quote.QuoteItem[0]);
        }
    }
}

注:為了使用方便,本系列所有示例都沒(méi)有直接采用IIS作為Web Server宿主,而是采用Visual Studio.Net自帶的臨時(shí)服務(wù)進(jìn)程,因此WSDL和Proxy的使用上,相關(guān)端口可能會(huì)變化。

進(jìn)一步改進(jìn)

上面的示例在客戶端處理上不算成功,因?yàn)樗枰蛻舫绦蛱峁〤oncreteService的Uri,怎么改進(jìn)呢?回憶我們通常對(duì)連接串的處置辦法:

  • 應(yīng)用邏輯使用一個(gè)邏輯的數(shù)據(jù)庫(kù)名稱,通過(guò)一個(gè)數(shù)據(jù)訪問(wèn)框架調(diào)用邏輯的數(shù)據(jù)庫(kù)。
  • 數(shù)據(jù)訪問(wèn)框架中有一個(gè)類似ConnectionManager的機(jī)制,負(fù)責(zé)把邏輯的數(shù)據(jù)庫(kù)連接名翻譯成實(shí)際的連接串。

對(duì)上面那個(gè)Web Service示例的也如法炮制,增加一個(gè)邏輯的Directory機(jī)制,實(shí)際工程中這個(gè)Directory可能就是個(gè)UDDI服務(wù),不過(guò)這里定義了一個(gè)精簡(jiǎn)對(duì)象。

圖5:為客戶程序增加服務(wù)Uri管理目錄機(jī)制

實(shí)現(xiàn)如下

C# IServiceDirectory
using System;
namespace Test.Client
{
    /// <summary>
    /// 抽象的服務(wù)目錄接口
    /// </summary>
    public interface IServiceDirectory
    {
        /// <summary>
        /// 通過(guò)索引器實(shí)現(xiàn)按名稱或取實(shí)際服務(wù)Uri 的機(jī)制。
        /// 為了約束客戶程序?qū)Ψ?wù)目錄的使用,僅提供一個(gè)readonly 的訪問(wèn)機(jī)制。
        /// </summary>
        /// <param name="name">邏輯的服務(wù)名稱</param>
        /// <returns>實(shí)際服務(wù)實(shí)體的Uri </returns>
        string this[string name] { get;}
    }
}
C# LocalServiceDirectory
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
namespace Test.Client
{
    class LocalServiceDirectory : IServiceDirectory
    {
        /// <summary>
        /// 保存邏輯服務(wù)名稱與具體Uri 對(duì)應(yīng)關(guān)系的目錄字典。
        /// </summary>
        private static IDictionary<string, string> dictionary = null;

        /// <summary>
        /// 靜態(tài)構(gòu)造的過(guò)程中,通過(guò)訪問(wèn)配置,獲取對(duì)應(yīng)關(guān)系。
        /// </summary>
        static LocalServiceDirectory()
        {
            NameValueCollection appSettings = ConfigurationManager.AppSettings;
            if ((appSettings == null) || (appSettings.Count <= 0)) return;
            dictionary = new Dictionary<string, string>();
            foreach (string name in appSettings.Keys)
                dictionary.Add(name, appSettings[name]);
        }

        public string this[string name]
        {
            get
            {
                string uri;
                if (!dictionary.TryGetValue(name, out uri))
                    return string.Empty;
                else
                    return uri;
            }
        }
    }
}
C# DirectoryServiceFactory
using System;
namespace Test.Client
{
    /// <summary>
    /// 為了隔離客戶程序?qū)?shí)際DirectoryService 類型的以來(lái),引入的服務(wù)目錄工廠。
    /// </summary>
    public static class DirectoryServiceFactory
    {
        /// <summary>
        /// 工廠方法。
        /// 世紀(jì)項(xiàng)目中,實(shí)體ServiceDirectory 類型可能運(yùn)行于遠(yuǎn)端服務(wù)器上,
        /// 或者就是UDDI服務(wù),獲取IServiceDirectory 過(guò)程可能還需要借助代理程序完成。
        /// </summary>
        /// <returns></returns>
        public static IServiceDirectory Create()
        {
            return new LocalServiceDirectory();
        }
    }
}
C# 修改后的客戶程序
using System;
using DemoService;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test.Client
{
    [TestClass]
    public class Client
    {
        [TestMethod]
        public void Test()
        {
            QuoteService service = new QuoteService();
            service.Url = DirectoryServiceFactory.Create()["QuoteService"];
  … …
        }
    }
}

進(jìn)一步討論

在有效的隔離了實(shí)體Web Service與抽象Web Service的關(guān)系后,之前設(shè)計(jì)模式、架構(gòu)模式中的那些套路就又有了用武之地,比如Observer、Adapter、Factory、Blackboard、MVC… …,甚至于Visitor這中雙因素以來(lái)的模式也可以套用,只不過(guò)原來(lái)的消息變成了XML SOAP、對(duì)象實(shí)體變成了XSD定義下的各種XML,至于UI上能看到的東西還有需要轉(zhuǎn)換的信息由XSL完成即可。


作者簡(jiǎn)介:王翔,軟件架構(gòu)師,主要方向?yàn)閄ML技術(shù)、.NET平臺(tái)開(kāi)發(fā)與集成、領(lǐng)域設(shè)計(jì)和公鑰基礎(chǔ)環(huán)境應(yīng)用。近年主要參與數(shù)據(jù)交換系統(tǒng)、自訂制業(yè)務(wù)領(lǐng)域語(yǔ)言平臺(tái)項(xiàng)目和信息安全類項(xiàng)目,工余時(shí)間喜歡旅游、寫作、解趣味數(shù)學(xué)問(wèn)題和烹飪。
加入書(shū)簽
digg+,
reddit+,
del.icio.us+,
dzone+
標(biāo)簽
XML

4 條回復(fù)

回復(fù)

或許應(yīng)該更進(jìn)一步的抽象 發(fā)表人 Anders Lin 發(fā)表于 2007年8月2日 下午11時(shí)52分
Re: 或許應(yīng)該更進(jìn)一步的抽象 發(fā)表人 hello hello 發(fā)表于 2007年8月3日 上午5時(shí)36分
Re: 或許應(yīng)該更進(jìn)一步的抽象 發(fā)表人 hello hello 發(fā)表于 2007年8月3日 上午5時(shí)36分
Re: 或許應(yīng)該更進(jìn)一步的抽象 發(fā)表人 hello hello 發(fā)表于 2007年8月3日 上午5時(shí)38分
  1. 返回頂部

    或許應(yīng)該更進(jìn)一步的抽象

    2007年8月2日 下午11時(shí)52分 發(fā)表人 Anders Lin

    目前的抽象僅是隔離Web Service的抽象和實(shí)現(xiàn),或許可以更進(jìn)一步,隔離接口和實(shí)現(xiàn)。接口的實(shí)現(xiàn)是調(diào)用web service還是調(diào)用本地,都不是client關(guān)心的。

  2. 返回頂部

    Re: 或許應(yīng)該更進(jìn)一步的抽象

    2007年8月3日 上午5時(shí)36分 發(fā)表人 hello hello

    確切地說(shuō)現(xiàn)在已經(jīng)是這樣了。
    Client使用的Service其實(shí)不是真正的Service,而是Service的Proxy類。
    是否使用Local,:), 其實(shí)也沒(méi)有關(guān)系,確切地說(shuō)把Assembly放到本地的話,加個(gè)Factory就可以區(qū)分WS還是本地的某Assembly中的某各類。

  3. 返回頂部

    Re: 或許應(yīng)該更進(jìn)一步的抽象

    2007年8月3日 上午5時(shí)36分 發(fā)表人 hello hello

    確切地說(shuō)現(xiàn)在已經(jīng)是這樣了。
    Client使用的Service其實(shí)不是真正的Service,而是Service的Proxy類。
    是否使用Local,:), 其實(shí)也沒(méi)有關(guān)系,確切地說(shuō)把Assembly放到本地的話,加個(gè)Factory就可以區(qū)分WS還是本地的某Assembly中的某各類。

  4. 返回頂部

    Re: 或許應(yīng)該更進(jìn)一步的抽象

    2007年8月3日 上午5時(shí)38分 發(fā)表人 hello hello

    確切地說(shuō)現(xiàn)在已經(jīng)是這樣了。
    Client使用的Service其實(shí)不是真正的Service,而是Service的Proxy類。
    是否使用Local,:), 其實(shí)也沒(méi)有關(guān)系,確切地說(shuō)把Assembly放到本地的話,加個(gè)Factory就可以區(qū)分WS還是本地的某Assembly中的某各類。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C#客戶端+PHP服務(wù)端的Web Service通信實(shí)現(xiàn)
用戶化JAXB綁定生成Java源代碼的簡(jiǎn)單嘗試
Java調(diào)用.NET webservice方法的幾種方式
深入研究SOAP消息
使用CXF發(fā)布和調(diào)用webservice之HelloWorld入門
用Axis 1.1 for Java進(jìn)行Web Services開(kāi)發(fā)(1)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服