2009-11-08 115 views
79

想知道在什麼情況下,您可以使用ChannelFactory調用調用時,希望從WCF服務生成代理?WCF ChannelFactory vs生成代理

這樣你就不必生成代理,並擔心在更新服務器時重新生成代理?

感謝

回答

82

有3點基本的方法創建一個WCF客戶端:

  1. 讓Visual Studio中生成代理。這個自動生成通過讀取WSDL連接到服務的代碼。如果服務因任何原因而更改,則必須重新生成該服務。這樣做的一大優點是設置起來很簡單 - VS有一個嚮導,而且全部都是自動的。缺點是你依靠VS爲你做了所有的辛苦工作,所以你失去了控制。

  2. 使用具有已知接口的ChannelFactory。這依賴於你具有描述服務的本地接口(服務契約)。最大的好處是可以更容易地管理變更 - 您仍然需要重新編譯和修改變更,但現在您不再重新生成代碼,而是引用新的接口。當你控制服務器和客戶端時,通常會使用它,因爲對於單元測試來說,這兩者都可以更容易地進行模擬。但是可以爲任何服務編寫接口,甚至是REST接口 - 請參閱this Twitter API

  3. 編寫您自己的代理 - 這很容易實現,特別是對於REST服務,使用HttpClientWebClient。這爲您提供了最好的穀物控制,但是以大量的服務API爲代價。例如:var content = new HttpClient().Get("http://yoursite.com/resource/id").Content; - 如果API的詳細信息發生更改,則在運行時纔會遇到錯誤。

就我個人而言,我從來不喜歡選項1 - 依靠自動生成的代碼是凌亂的,失去太多的控制。此外,它經常會產生序列化問題 - 我最終得到兩個完全相同的類(一個在服務器代碼中,一個是自動生成的),它可以被拖拽但很痛苦。

選項2應該是完美的,但頻道有點太有限 - 例如它們是completely lose the content of HTTP errors。這就是說,描述服務的接口更容易編碼和維護。

+2

@MurHaf Nope - 這個答案完全是我自己的工作。我總是歸因於他人的貢獻。我寫了這個答案的基礎是多年來在各種工作中使用.Net中的SOAP服務。您鏈接的文章來自2013年3月,而我的答案是在2010年4月 - 3年前寫的!如果剽竊已經發生,他會複製我。在提出指控之前,您應該查看日期,因爲這很容易做到。 – Keith 2013-12-11 21:37:08

+0

@MurHaf我們甚至沒有得出相同的結論 - 該文章建議自動生成代理(選項1)爲'簡單'。我形容它很容易設置,但混亂和痛苦要保持。他甚至不會討論編寫自己的代理(選項3)。 – Keith 2013-12-12 09:24:17

+1

我認爲SvcUtil也應該被提及,因爲這是「寫」客戶端的最常用方法之一。 – 2014-08-19 15:52:48

11

那麼爲了使用ChannelFactory<T>你必須願意在服務和客戶端之間共享合同組件。如果這對你很好,那麼ChannelFactory<T>可以爲你節省一些時間。

+2

這是不正確的。 – 2011-12-02 19:57:44

+0

@Charles - 你能解釋爲什麼這不是事實嗎? – 2011-12-14 00:22:01

+5

@Aran:我認爲安德魯的意思是正確的 - 如果您不想生成合約類的傳真,那麼您需要訪問原件。確實有這種或那種你需要擁有那些合約類別。您可以生成它們,手動編寫它們,或者獲取服務源代碼(如果它使用相同的語言)。共享程序集是最簡單的方法,但這並非總是可行。 (也許我只是從字面上理解Andrew,但清晰度在這裏很重要。) – 2011-12-14 17:43:34

8

該代理將構建異步功能,這是一種很好的方式。

+2

是的 - 同時,在命令行中,Visual Studio的「添加服務引用」以及svcutil.exe會將配置超出識別範圍,並至少在svcutil.exe中定義一個「/ noconfig」開關..... – 2009-11-09 06:12:19

+1

ChannelFactory還提供了異步方法:http://msdn.microsoft.com/en-us/library/ms731177.aspx 但我更喜歡使用T4模板來創建一個使用ThreadPool的異步類,它將調用同步方法。 – SandRock 2011-04-12 16:46:48

+0

什麼是T4模板? – TheWommies 2011-12-06 10:52:32

20

我使用ChannelFactory和MetadataResolver.Resolve方法。客戶端配置是一件麻煩的事情,所以我從服務器獲取我的ServiceEndpoint。

當您使用ChannelFactory(Of T)時,T可以是您可以從項目中的引用或生成的合同實例中獲得的原始合同。在某些項目中,我從Service Reference生成代碼,因爲我無法添加對合同DLL的引用。您甚至可以與服務參考生成異步合同,並使用ChannelFactory的合同接口。

對我來說使用ChannelFactory的主要目的是擺脫WCF客戶端配置信息。在下面的示例代碼中,您可以看到如何在沒有配置的情況下實現WCF客戶端。

Dim fixedAddress = "net.tcp://server/service.svc/mex" 
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress)) 
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0)) 
accesService = factoryService.CreateChannel() 

在我的最終項目中,檢查availableBindings以使用net.tcp或net.pipe(如果可用)。這樣,我可以使用最適合我的需求的可用綁定。我只依賴於服務器上存在元數據端點的事實。

我希望這有助於

順便說一句,這是使用.NET 3.5完成的。但它也可以與4.0一起工作。

+0

真棒的東西。我也使用MetadataResolver.Resolve作爲配置,但我沒有考慮解決從服務器綁定。非常好的一點! – 2011-10-21 05:28:15

+0

upvote提到'使用ChannelFactory擺脫WCF客戶端配置的主要觀點 – Kurubaran 2016-01-03 22:25:20

7

我的答案是一種總結Keith'sAndrew Hare's的答案。

如果您不控制服務器,但只有使用Visual Studio或svcutil的WSDL/URL生成代理。 (請注意,當svcutil工作得更好時,Visual Studio有時會失敗)。

當您同時控制服務器和客戶端時,共享接口/合同並調用ChannelFactory

2

這不僅僅是一個節省時間的問題。使用WSDL生成的代理很危險,因爲如果您忘記更新服務引用,則可能會使解決方案處於不一致的狀態。一切都在編譯,但服務合同已經中斷。我明確地建議儘可能使用ChannelFactory,讓你的生活更輕鬆。

一個可能的選擇可能是編寫一個預構建腳本,每次構建項目時調用SVCUtil實用程序來創建代理,但無論如何ChannelFactory更加整潔優雅。