天天看點

WCF分布式開發步步為赢(5)服務契約與操作重載

【1】重載概念:

【1.1】什麼是重載(OverLoad):

    所謂重載是指同一個方法名可以對應着多個方法的實作。這些方法的名字相同,但是方法的參數的類型不同。這就是方法重載的概念。函數方法類和對象的應用尤其重要。

 方法重載要求編譯器能夠唯一地确定調用一個方法時應執行哪個方法代碼,即采用哪個方法實作。确定方法實作時,要求從方法參數的個數和類型上來區分。這就是說,進行方法重載時,要求同名方法在參數個數上不同,或者參數類型上不同。否則,将無法實作重載。

    關于重載一定要注意:重載方法的參數類型和參數個數一定要不同(即:要麼參數的類型不同,要麼參數的個數不同,要麼參數的類型和個數都不同),否則,編譯器就不知道該調用那個方法了。

   方法重載的好處就是相同的方法,帶來不同的結果和實作,這裡我們可以根據傳遞參數的不同來決定調用飛方法。這是編譯時多态的一種實作機制。

【1.2】C#類方法重載示例:

    我們這裡給出一個簡單的c#語言實作的方法重載的列子,這裡對于SayHelloOverLoading方法,同一個類裡給出的三個方法的參數個數不同。内部實作也不同。具體代碼如下:

//3.面向對象裡的類,如何實作操作重載,和WCF服務類裡的操作重載做對比

    public class ClassOverLoading

    {

        public ClassOverLoading()

        { 

        }

        //掩飾方法重載,分别實作三個方法,C#等面向對象的語言提供了方法重載機制的支援。

        public string SayHelloOverLoading()

            //編寫代碼

            return "Hello,This an C# class overloading demo";

        //類裡的方法重載不需要别名

        public string SayHelloOverLoading(string name)

        {

            return "Hello:" + name + "This an C# class overloading demo";

        public string SayHelloOverLoading(string firstName, string lastName)

            return "Hello:" + firstName + lastName + "This an C# class overloading demo";

    }

【2】操作重載:

【2.1】操作重載:

    WCF服務支援核心的Web 服務協定,同樣其中繼資料交換也是基于XML語言描述,用戶端通過WSDL檔案來了解服務方法相關的資訊,包括參數的個數、類型、傳回值、調用順序等重要資訊。由于WSDL不支援方法的重載,是以我們的WCF服務操作重載就無法通過WSDL暴露給用戶端。如果我們在服務契約裡定義了方法的重載,編譯可以正常通過,但是啟動服務宿主就會抛出System.InvalidOperationException異常,如下圖:

  是以我們不能在WCF服務類了定義和實作方法重載,否則無法暴露為服務操作。

【2.2】解決辦法:

   WCF給我們提供了一個解決辦法,讓我們可以在WCF服務類裡使用服務操作的重載。WCF定義了一個機制OperationContract,使用OperationContract特性的Name屬性,為操作指定别名:

[AttributeUsage(AttributeTargets.Method)]

public sealed class OperationContractAttribute : Attribute

{

   public string Name

   {get;set;}

   //更多成員

}

【3】代碼實作分析:

    下面我們來給出一個具體的WCF服務實作操作重載,包括服務定義、宿主配置、用戶端引用和測試的完整過程。

【3.1】服務契約:

    定義了服務契約IWCFOverLoadingService,分别給出SayHelloOverLoading操作契約的3種不同定義和WCFService服務類裡的實作。具體代碼如下:

    //1.服務契約,操作契約重載

    [ServiceContract(Namespace = "http://www.cnblogs.com/frank_xl/")]

    public interface IWCFOverLoadingService

        //操作契約

        [OperationContract(Name = "SayHelloOverLoading1")]

        string SayHelloOverLoading();

        [OperationContract(Name = "SayHelloOverLoading2")]

        string SayHelloOverLoading(string name);

        [OperationContract(Name = "SayHelloOverLoading3")]

        string SayHelloOverLoading(string firstName, string lastName);

    //2.服務類,內建接口。實作契約

    public class WCFService : IWCFOverLoadingService

        //實作接口定義的方法

            Console.WriteLine("Hello! ,This an overloading demo for WCF Service 

WCF分布式開發步步為赢(5)服務契約與操作重載

");

            return "Hello! This an overloading demo for WCF Service 

WCF分布式開發步步為赢(5)服務契約與操作重載

 ";

            Console.WriteLine("Hello! {0},This an overloading demo WCF Service 

WCF分布式開發步步為赢(5)服務契約與操作重載

", name);

            return "Hello! " + name + ", This an overloading demo for WCF Service 

WCF分布式開發步步為赢(5)服務契約與操作重載

";

            Console.WriteLine("Hello! {0}    {1},This an overloading demo WCF Service

WCF分布式開發步步為赢(5)服務契約與操作重載

", firstName, lastName);

            return "Hello! " + firstName + " " + lastName + ", This an overloading demo for WCF Service 

WCF分布式開發步步為赢(5)服務契約與操作重載

"; ;

【3.2】托管宿主:

   自定義托管宿主使用配置檔案來定義服務的終結點和中繼資料交換節點,服務的交換行為等其他屬性也在配置檔案裡給出,我們配置了三種不同的資料服務通信方式,分别是http、tcp、IPC.具體配置資訊如下:

<services> 

            <service behaviorConfiguration="WCFService.WCFServiceBehavior" name="WCFService.WCFService"> 

                <endpoint 

                    address="http://localhost:9001/WCFService" 

                    binding="wsHttpBinding" 

                    contract="WCFService.IWCFOverLoadingService"> 

                </endpoint> 

                    address="net.tcp://localhost:9002/WCFService" 

                    binding="netTcpBinding" 

                address="net.pipe://localhost/WCFService" 

                binding="netNamedPipeBinding" 

                contract="WCFService.IWCFOverLoadingService"> 

                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 

                <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> 

                <endpoint address="mex" binding="mexNamedPipeBinding" contract="IMetadataExchange" /> 

                <host> 

                    <baseAddresses> 

                        <add baseAddress="http://localhost:9001/"/> 

                        <add baseAddress="net.tcp://localhost:9002/"/> 

                        <add baseAddress="net.pipe://localhost/"/> 

                    </baseAddresses> 

                </host> 

            </service> 

        </services> 

        <behaviors> 

            <serviceBehaviors> 

                <behavior name="WCFService.WCFServiceBehavior"> 

                    <serviceMetadata httpGetEnabled="true" /> 

                    <serviceDebug includeExceptionDetailInFaults="false" /> 

                </behavior> 

            </serviceBehaviors> 

        </behaviors>

【3.3】用戶端服務引用:

    我們來分别添加對服務端的引用,首先啟動托管宿主程式。然後使用Visual Studio2008工具直接添加服務引用,你也可以使用svcUtil.exe工具,如圖所示:

    用戶端輸入服務的基位址,查找服務,成功夠我們可以看到服務契約的資訊,這裡顯示的3個操作名稱已經不同,實際上這裡給出的是三個不同名稱的服務方法。輸入命名空間,确定即可完成。

【3.4】代理代碼:

    用戶端反序列化生成的服務契約等資訊,我們檢視操作契約對應的用戶端方法名稱以及改變,這樣一來,用戶端就沒有實作對應的方法重載,也就不能使用重載帶來的優勢,也即是編譯時多态的特性。手動更改用戶端服務代理類和服務契約代碼,使之支援操作方法重載,代碼如下:

public interface IWCFOverLoadingService {

        [System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading1" ,Action="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1", ReplyAction="http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading1Respon" +

            "se")]

        [System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading2", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading2Respon" +

        [System.ServiceModel.OperationContractAttribute(Name = "SayHelloOverLoading3", Action = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3", ReplyAction = "http://www.cnblogs.com/frank_xl/IWCFOverLoadingService/SayHelloOverLoading3Respon" +

    這樣我們用戶端方法也支援操作方法的重載特性。

【3.5】用戶端測試代碼:

    為了測試操作契約,我們在用戶端應用裡添加了部分的測試代碼,這裡為了測試服務端定義的不同的操作。我們分組按照協定給出了測試的代碼:

            //執行個體化用戶端服務代理Tcp

            ServiceOverLoadingTcp.WCFOverLoadingServiceClient wcfServiceProxyTcp =

                new ServiceOverLoadingTcp.WCFOverLoadingServiceClient("WSHttpBinding_IWCFOverLoadingService1");

            Console.WriteLine("Test call service using TCP--------------------.");

            //通過代理調用SayHelloOverLoading服務,分别傳遞不同的參數,進行測試

            Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading());

            Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Frank Xu Lei"));

            Console.WriteLine(wcfServiceProxyTcp.SayHelloOverLoading("Lei", "Xu"));

            //執行個體化用戶端服務代理Http

            ServiceOverLoadingHttp.WCFOverLoadingServiceClient wcfServiceProxyHttp =

                new ServiceOverLoadingHttp.WCFOverLoadingServiceClient("NetTcpBinding_IWCFOverLoadingService");

            Console.WriteLine("Test call service using Http-------------------");

            Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading());

            Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Frank Xu Lei"));

            Console.WriteLine(wcfServiceProxyHttp.SayHelloOverLoading("Lei", "Xu"));

            //Debuging

            Console.WriteLine("Press any key to continue

WCF分布式開發步步為赢(5)服務契約與操作重載

            Console.Read();

【4】運作結果:

    這裡分别調用三種服務操作,進行測試。運作的結果如圖所示:

【5】總結:

     以上就是本節對WCF服務操作重載的介紹,包括一般重載的基本定義和c#語言中簡單的方法重載的實作。然後介紹了WCF操作重載的實作機制、局限性和解決辦法,服務契約預設不支援操作方法重載,我們可以利用WCF已有的機制給出方法的别名來解決這個問題。然後給出了包括用戶端等完整的測試解決方案,用戶端反序列話生成服務類預設不支援服務操作方法重載的,生成的也是服務操作的别名方法。我們在用戶端要想使服務代理類支援重載,以利用重載的優勢,就需要重新修改用戶端服務代理代碼。 另外給出本節的執行個體代碼供大家參考:

參考資料:

 本文轉自 frankxulei 51CTO部落格,原文連結:http://blog.51cto.com/frankxulei/320409,如需轉載請自行聯系原作者