絳河 初識WCF5

然后我們在<Client>中添加一個終結點,這個是客戶端的終結點,我們前面曾經提過,通信實際上發生在兩個終結點間,客戶端也有個終結點,然而請求總是從客戶端首先發起,所以終結點地址應該填寫為服務端終結點的地址讓客戶端來尋址,但是服務協定要客戶端本地是有的,所以這個要寫本地定義的那個協定的完全限定名:

?

引用http://blog.csdn.net/songyefei/article/details/7389186

第五篇 再探通信--ClientBase

?

在上一篇中,我們拋開了服務引用和元數據交換,在客戶端中手動添加了元數據代碼,并利用通道工廠ChannelFactory<>類創建了通道,實現了和服務端的通信。然而,與服務端通信的編程模型不只一種,今天我們來學習利用另外一個服務類ClientBase<>來完成同樣的工作,了解了這個類的使用方法,我們對服務引用中的關鍵部分就能夠理解了。

?

?

?

ClientBase<>類也是一個泛型類,接受服務協定作為泛型參數,與ChannelFactory<>不同的是,這個類是一個基類,即抽象類,是不能實例化成對象直接使用的,我們需要自己寫一個類來繼承這個類,我們新寫的類實例化出來就是客戶端代理了,這個對象可以調用基類的一些受保護的方法來實現通信。ClientBase<>為我們封裝的很好,我們只需要寫個新類來繼承他就可以了,通信的很多部分他都替我們做好了,比如我們不用進行去創建通道和打開通道的操作,直接調用協定方法就可以了。這也是服務引用和其他元數據生成工具(如svcutil)使用這個類來構造客戶端代理的原因。

?

?

?

我們一邊動手一邊學習

?

?

?

1. 建立客戶端程序

?

我們依然不用服務引用,完全手寫,這次還是建立一個控制臺應用程序作為客戶端。

?

2. 添加必要的引用

?

我們用到的ClientBase<>類在System.ServiceModel程序集中,因此,要添加這個程序集的引用,同時在program.cs中添加using語句

    1. using?System.ServiceModel;?

這一步應該很熟了,如果有疑問,返回前幾篇溫習一下。

因為沒有使用服務引用,客戶端現在沒有任何元數據的信息,我們要來手寫。首先把服務協定寫進去。這個再熟悉不過了(寫在Program類后面):

    [ServiceContract]  public interface IHelloWCF  {  [OperationContract]  string HelloWCF();  }  

4. 編寫客戶端代理類

上面已經提到,我們要自己寫一個新類來繼承ClientBase<>基類,這樣這個新類就是代理類了,同時,為了能夠用代理類直接調用服務協定的方法,我們還要讓代理類實現服務協定的接口,注意,繼承要寫在前面,實現接口要寫在后面。我們把這個類起名為HelloWCFClient。

    public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  {   }  

ClientBase<>有許多的構造函數,接受不同種類的參數來創建代理類對象,其實這些參數都是元數據信息,剛才我們已經通過泛型參數傳遞給基類服務協定這個元數據了,現在基類還需要綁定和終結點地址這兩個元數據才能正確創建連接,所以我們繼承的新類應該把這個構造函數給覆載一下接受這兩種元數據參數并傳遞給基類。

public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  
{  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  
} 

我們看到這個新建的構造函數什么也沒做,只是接受了兩個參數,一個是綁定,一個是終結點地址,然后直接調用基類(也就是ClientBase<>)的構造函數,把這個兩個參數傳遞了上去。其實工作都是ClientBase<>做的,我們新建的類就是個傳話的,要不然怎么叫代理呢,他什么活都不干。

既然我們實現了服務協定接口,當然要實現接口的方法了。下面我們把方法的實現寫下來:

public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  
{  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  public string HelloWCF()  {  return base.Channel.HelloWCF();  }  
} 

別忘了你的處境,凡人!我們這是在客戶端啊,怎么可能有服務協定呢?這個可以有,但是這個實現不是我們在做,而是要和服務端通信讓服務端做,這里可以看到代理鮮明的特點了,代理類雖然實現了服務協定的方法,但是在方法中,他調用了基類(就是ClientBase<>)上的通道,并通過通道調用了了協定方法。此時,ClientBase<>已經為我們建立好與服務端的通道了,而且是用服務協定建立的,我們當然可以在通道上調用服務協定的方法。所以調用代理類對象的HelloWCF()的過程是代理類委托基類在已經建立好的服務協定通道上調用協定方法,并從服務端獲得返回值,然后再返回給代理類對象的調用者。狗腿啊狗腿。

5. 編寫程序主體

代理類已經寫完了,我們現在開始寫程序的主體,讓我們來到Program的Main函數中。

還是有一些準備要做,還差兩個元數據呢,對了,就是綁定和地址。和上一篇一樣,我們先建立這個兩個元數據的對象備用:

    WSHttpBinding binding = new WSHttpBinding();  EndpointAddress remoteAddress = new EndpointAddress("http://localhost/IISService/HelloWCFService.svc");  

接下來就要建立我們的代理類對象了,new一個出來吧:

    HelloWCFClient client = new HelloWCFClient(binding, remoteAddress);  

把我們剛剛建立的兩個元數據對象作為參數傳遞進去。

?

接下來就可以調用服務協定方法了:

string result = client.HelloWCF(); 


別忘了關閉通道,ClientBase<>很貼心的為我們準備了這個方法,不用再做強制類型轉換什么的了(見前一篇)。

client.Close();?

以下是Program.cs的全部代碼:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  using System.ServiceModel;  namespace ConsoleClient  
{  class Program  {  static void Main(string[] args)  {  WSHttpBinding binding = new WSHttpBinding();  EndpointAddress remoteAddress = new EndpointAddress("http://localhost/IISService/HelloWCFService.svc");  HelloWCFClient client = new HelloWCFClient(binding, remoteAddress);  string result = client.HelloWCF();  client.Close();  Console.WriteLine(result);  Console.ReadLine();  }  }  [ServiceContract]  public interface IHelloWCF  {  [OperationContract]  string HelloWCF();  }  public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  {  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  public string HelloWCF()  {  return base.Channel.HelloWCF();  }  }  
} 

6. 再展開一點點

這樣看上去已經挺成功了,我們現在再打開服務引用的reference.cs代碼,看看是不是大部分都看得懂了?監管有些地方他寫的可能有些復雜,比如描述協定的屬性參數啊,代理類更多的構造函數啊,但是核心的就是我們剛剛寫的部分,那一大堆wsdl什么的其實都不是核心,不信的話你把他們都刪掉,就留一個reference.cs看看還好不好用?那一堆東西也不是沒用就是現在自己看起來還蠻復雜的,我們到后面一點點學習。

?

我們仔細看服務引用的reference.cs代碼,有一樣東西是我們有而他沒有的,那就是對終結點地址和綁定的建立,而且在使用服務引用的時候我們也沒有提供之兩樣東西,直接掉服務協定方法就行了(見第一篇),那么服務引用是從哪里找到這兩個關鍵的元數據元素呢?

?

就在配置文件里,我們做的客戶端還沒有配置文件,我們可以把這兩個元素都放在配置文件里,這樣就可以避免硬編碼了。

?

為我們的控制臺應用程序添加一個應用程序配置文件。方法是右鍵點擊項目->添加->新建項->應用程序配置文件。保持默認名稱app.config。

打開來看,里面沒寫什么實際的內容:

    <?xml version="1.0" encoding="utf-8" ?>  <configuration>  </configuration>  

我們對配置服務應該不陌生,如果忘記了,翻回到第二篇去回顧一下。

首先還是要添加<System.ServiceModel>節,無論是服務端還是客戶端,只要是WCF的服務配置都要在這個節里面:

<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  <system.serviceModel>  </system.serviceModel>  
</configuration> 

在這里我們要配置的是客戶端,所以我們不添加<Services>節了,而改成<Client>:

    <?xml version="1.0" encoding="utf-8" ?>  <configuration>  <system.serviceModel>  <client>  </client>  </system.serviceModel>  </configuration>  

?

如果你忘記了我們在第三篇中配置的IIS服務的內容,可能稍有迷惑,這里的地址看上去是個服務地址而不是終結點地址,這是因為我們在IIS中把終結點地址設置為了空字符串,此時服務地址就是終結點地址了。注意看后面的contract,他的完全限定名的命名空間是客戶端程序的命名空間ConsoleClient,這也表示這個類型是定義在本地的,不要搞錯了。

?

保存,配置已經寫完了,你如果看服務引用為我們生成的配置會看到一堆東西,實際上核心的就是這些。

?

既然我們已經在配置中聲明了綁定和終結點地址,在代碼中就不再需要了。

首先我們修改一下代理類,為他提供一個沒有參數的構造函數,否則在new他的時候他會非管我們要兩個參數。

public HelloWCFClient()  : base()  
{   } 

還是什么也不做,直接調基類的無參構造函數。

?

然后修改一下Main函數,去掉終結點對象和地址對象的聲明,并用無參構造函數來new 代理類的實例:

    static void Main(string[] args)  {  HelloWCFClient client = new HelloWCFClient();  string result = client.HelloWCF();  client.Close();  Console.WriteLine(result);  Console.ReadLine();  }  

F5運行一下,結果如一吧!

到這里已經和服務引用的感覺基本一樣了,我們已經寫出了服務引用的核心部分。

以下是修改后的Program.cs完整代碼:

    using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.ServiceModel;  namespace ConsoleClient  {  class Program  {  static void Main(string[] args)  {  HelloWCFClient client = new HelloWCFClient();  string result = client.HelloWCF();  client.Close();  Console.WriteLine(result);  Console.ReadLine();  }  }  [ServiceContract]  public interface IHelloWCF  {  [OperationContract]  string HelloWCF();  }  public class HelloWCFClient : ClientBase<IHelloWCF>, IHelloWCF  {  public HelloWCFClient()  : base()  {   }  public HelloWCFClient(System.ServiceModel.Channels.Binding binding, EndpointAddress remoteAddress)  : base(binding, remoteAddress)  {   }  public string HelloWCF()  {  return base.Channel.HelloWCF();  }  }  }  

7. 總結

通過本篇的學習,我們熟悉了另一種與服務端通信的辦法,即通過ClientBase<>派生代理類的方法,這種方法實際上就是服務引用使用的方法,可以說我們已經在最簡單級別上手寫了一個服務引用的實現。

?

使用ChannelFactory<>和ClientBase<>都可以實現與服務端的通信,這是類庫支持的最高層次的通訊方法了,其實還有更底層的通道通信方法,我們現在就不再深入了。而選擇這兩種方法完全取決于開發人員,有人喜歡工廠,有人喜歡代理類。既然我們都已經掌握了,就隨意選擇吧。

?

至此,我們對通信有了一個基本的了解,只能算一個初探吧。然而我相信這一次的小小深入會對我們今后的學習帶來大大的幫助的。

?

轉載于:https://www.cnblogs.com/janghe/p/7594217.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251791.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251791.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251791.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python修煉第四天

今天換了師傅。江湖人稱景女神^o^。 女師傅講的比較細&#xff0c;原理的比較多。初學者來說有些難。但是基本功是必須要打牢的。努力&#xff01; 迭代器 迭代器&#xff0c;迭代的工具1 什么是迭代&#xff0c;指的是一個重復的過程&#xff0c;每一次重復稱為一次迭代&#…

尷尬的存儲過程

最近在給一個已沉淀了多年的系統框架進行優化&#xff0c;發現大部分的基礎業務&#xff08;比如增刪改&#xff09;的實現都是通過存儲過程來實現。這讓我糾結了很久&#xff0c;看了下代碼格式我猜應該都是使用了代碼生成器。這無疑為系統的擴展留下了一個難以彌補的大坑。 首…

java虛擬機06-內存分區/新生代、老年代

1.原因 JVM在程序運行過程當中&#xff0c;會創建大量的對象&#xff0c;這些對象&#xff0c;大部分是短周期的對象&#xff0c;小部分是長周期的對象&#xff0c;對于短周期的對象&#xff0c;需要頻繁地進行垃圾回收以保證無用對象盡早被釋放掉&#xff0c;對于長周期對象&a…

博客作業04--樹

1.學習總結(2分) 1.1樹結構思維導圖 1.2 樹結構學習體會 樹這一章節比較復雜&#xff0c;知識點繁多&#xff0c;結合了遞歸的知識所以代碼閱讀起來會有障礙&#xff0c;難以理解&#xff0c;所以學起來比較吃力&#xff0c;而且很多經典的算法理解的不是很透徹解決pta上的問題…

Centos 配置多個虛擬IP

Centos 配置多個虛擬IP 臨時設置 ifconfig enp2s0:3 192.168.3.152 netmask 255.255.255.0 up 復制代碼永久生效 TYPEEthernet BOOTPROTOnone NAMEenp2s0 DEVICEenp2s0 HWADDR40:8d:5c:bc:f4:d8 ONBOOTyes IPADDR0192.168.3.200 PREFIX024 GATEWAY0192.168.3.254 IPADDR1192.16…

[轉]MySQL日志——Undo | Redo

本文是介紹MySQL數據庫InnoDB存儲引擎重做日志漫游 00 – Undo LogUndo Log 是為了實現事務的原子性&#xff0c;在MySQL數據庫InnoDB存儲引擎中&#xff0c;還用Undo Log來實現多版本并發控制(簡稱&#xff1a;MVCC)。 - 事務的原子性(Atomicity) 事務中的所有操作&#xff0…

Vim操作指南

vim具有6種基本模式和5種派生模式。 基本模式 普通模式 插入模式 可視模式 選擇模式 命令行模式 Ex模式 派生模式 操作符等待模式 插入普通模式 插入可視模式 插入選擇模式 替換模式 1.移動光標&#xff08;普通模式下&#xff09; h&#xff1a;左 j&#xff1a;下 …

[DP/單調隊列]BZOJ 2059 [Usaco2010 Nov]Buying Feed 購買飼料

首先我想吐槽的是題目并沒有表明數據范圍。。。 這個題目 DP方程并不難表示。 dp[i][j]表示前i個地點攜帶了j個貨物的最小花費 dp[i][j] dp[i-1][k] (j-k) * cost j*j*(leng[i]-leng[i-1]) 如果你這樣直接提交上去&#xff0c;恭喜你超時&#xff01;&#xff01;&#xff0…

十天沖刺09

今天&#xff0c;和小伙伴在做密保功能的開發&#xff0c;而且通過密保可以找回用戶密碼。轉載于:https://www.cnblogs.com/Excusezuo/p/10923690.html

hdu 6168 Numbers

zk has n numbers a1,a2,...,an. For each (i,j) satisfying 1≤i<j≤n, zk generates a new number (aiaj). These new numbers could make up a new sequence b1&#xff0c;b2,...,bn(n?1)/2 . LsF wants to make some trouble. While zk is sleeping, Lsf mixed up seq…

039_MySQL_多表查詢

#創建部門 CREATE TABLE IF NOT EXISTS dept (did int not null auto_increment PRIMARY KEY,dname VARCHAR(50) not null COMMENT 部門名稱 )ENGINEINNODB DEFAULT charset utf8;#添加部門數據 INSERT INTO dept VALUES (1, 教學部); INSERT INTO dept VALUES (2, 銷售部); IN…

sqlserver 創建對某個存儲過程執行情況的跟蹤

有時候需要抓取執行存儲過程時某個參數的值&#xff0c;有時候程序調用存儲過程執行后結果不太對&#xff0c;不確定是程序的問題還是存儲過程的問題&#xff0c;需要單獨執行存儲過程看結果 即可用下面的方法 -- --創建對某個存儲過程的執行情況的跟蹤 --注意修改路徑 和 obje…

5.7 彈性盒子

彈性盒子定義彈性盒子 display&#xff1a;flex定義子元素排列方式 flex-diection定義子元素換行方式 flxe-wrap定義子元素對齊方式橫向對齊 justify-content縱向對齊 align-items 媒體查詢 media screen and (max-width:最大寬度)and &#xff08;min-width&#xff1a;最小…

4.navicat11激活教程,親測可用哦!

原文地址&#xff1a;http://blog.csdn.net/sanbingyutuoniao123/article/details/52589678Navicat是一款數據庫管理工具, 用于簡化, 開發和管理MySQL, SQL Server, SQLite, Oracle 和 PostgreSQL 的數據庫&#xff1b;Navicat數據模型工具以圖形化方式創建關聯式數據庫&#x…

漢諾塔問題深度剖析(python實現)

當我們學習一門編程語言的時候&#xff0c;都會遇到遞歸函數這個問題。而學習遞歸的一個經典案例就是漢諾塔問題。通過這篇文章&#xff0c;觀察移動三個盤子和四個盤子的詳細過程&#xff0c;您不僅可以深刻的了解遞歸&#xff0c;也更加熟悉了漢諾塔的游戲的玩法。 更好的閱讀…

iOS-QQ臨時對話、QQ群申請跳轉

QQ 臨時對話 NSString *qq [NSString stringWithFormat:"mqq://im/chat?chat_typewpa&uin%&&version1&src_typeweb","這是是QQ號碼"];NSURL *urlQQ [NSURL URLWithString:qq];[[UIApplication sharedApplication] openURL:urlQQ]; QQ 申…

[luoguP2331] [SCOI2005]最大子矩陣(DP)

傳送門 orz不會做。。。 一個好理解的做法&#xff08;n^3*k&#xff09;&#xff1a; 分n1和n2兩種情況考慮。 n1時&#xff0c;預處理出前綴和sum[]。 設f[i][j]為到達第i格&#xff0c;已經放了j個子矩陣的最大和&#xff0c; 那么每次先把f[i][j]的值設為f[i-1][j]&#xf…

想要去阿里面試?你必須得跨過 JVM 這道坎!

概述 很多人想要到阿里巴巴、美團、京東等互聯網大公司去面試&#xff0c;但是現在互聯網大廠面試一般都必定會考核JVM相關的知識積累和實踐經驗&#xff0c;畢竟線上系統寫好代碼部署之后&#xff0c;每個工程師都必須關注JVM相關的東西&#xff0c;比如OOM、GC等問題. 所以一…

醫學知識圖譜一

大綱 知識自動提取技術 醫學知識融合 醫學知識推理 轉載于:https://www.cnblogs.com/quietwalk/p/9000950.html

在一個div里,列表樣式圖片進行float,實現水平排序

<div class"xiangce"><ul> <li><a href"#"><img src"images/pic4.gif" alt"">產品名稱</a></li><li><a href"#"><img src"images/pic4.gif" alt"…