2012-04-07 79 views
9

將單向monotouch編譯爲本地代碼,因此它具有一些限制,如動態調用是不允許的。我使用ChannelFactory動態來調用wcf服務:new ChannelFactory(myBinding,myEndpoint);現在單擊我應該使用slsvcutil生成wcf代理類,但由於通過ClientBase類與WCF基礎結構高度耦合,slsvcutil會生成大量不必要的額外代碼(巨大),並且使用戶難以進行單元測試。單擊/ WCF:如何在不使用svcutil的情況下使用wcf服務

除了ChannelFactory,還有更好的解決方案嗎?我寧願手動編寫代碼,更多地控制如何調用服務,如ChannelFactory。

==========

 ChannelFactory<IMyContract> factory = new ChannelFactory<IMyContract>(binding, endpointAddress); 
     return factory.CreateChannel(); 

// ==>它拋出異常:MonoTouch中不支持動態代理代碼生成。覆蓋此方法或調用者返回特定的客戶端代理實例

回答

13

ChannelFactory<T>有一個虛擬方法CreateChannel()。如果這不被覆蓋,它會使用動態代碼生成,這在MonoTouch上會失敗。

解決方案是覆蓋它並提供您自己的編譯時實現。

下面是我的舊服務實現,至少用於在MonoTouch上工作。我將它分成2個部分類 - 第一個在所有構建中鏈接,第二個在iOS構建中(允許動態生成機制仍然可以在Windows上工作)。
我已經剝離它只包含1服務電話。

TransactionService.cs:

public partial class TransactionService : ClientBase<IConsumerService>, IConsumerService 
{ 

    public TransactionService() 
    { 
    } 

    public TransactionService(string endpointConfigurationName) : 
     base(endpointConfigurationName) 
    { 
    } 

    public TransactionService(string endpointConfigurationName, string remoteAddress) : 
     base(endpointConfigurationName, remoteAddress) 
    { 
    } 

    public TransactionService(string endpointConfigurationName, EndpointAddress remoteAddress) : 
     base(endpointConfigurationName, remoteAddress) 
    { 
    } 

    public TransactionService(Binding binding, EndpointAddress remoteAddress) : 
     base(binding, remoteAddress) 
    { 
    } 

    public AccountBalanceResponse GetAccountBalance(AccountBalanceQuery query) 
    { 
     return Channel.GetAccountBalance(query); 
    } 
} 

TransactionService.iOS.cs: ConsumerServiceClientChannel,其執行通過反射調用)

public partial class TransactionService 
{ 
    protected override IConsumerService CreateChannel() 
    { 
     return new ConsumerServiceClientChannel(this); 
    } 

    private class ConsumerServiceClientChannel : ChannelBase<IConsumerService>, IConsumerService 
    { 

     public ConsumerServiceClientChannel(System.ServiceModel.ClientBase<IConsumerService> client) : 
      base(client) 
     { 
     } 

     // Sync version 
     public AccountBalanceResponse GetAccountBalance(AccountBalanceQuery query) 
     { 
      object[] _args = new object[1]; 
      _args[0] = query; 
      return (AccountBalanceResponse)base.Invoke("GetAccountBalance", _args); 
     } 

     // Async version 
     public IAsyncResult BeginGetAccountBalance(AccountBalanceQuery query, AsyncCallback callback, object asyncState) 
     { 
      object[] _args = new object[1]; 
      _args[0] = query; 
      return (IAsyncResult)base.BeginInvoke("GetAccountBalance", _args, callback, asyncState); 
     } 


     public AccountBalanceResponse EndGetAccountBalance(IAsyncResult asyncResult) 
     { 
      object[] _args = new object[0]; 
      return (AccountBalanceResponse)base.EndInvoke("GetAccountBalance", _args, asyncResult); 
     } 

    } 
} 

編輯:我只是用最新的測試此MT(5.2) - 它不再需要以前的那些額外的鍋爐板,只需要CreateChannel()覆蓋。我已經清理了示例代碼來匹配。

EDIT2:我添加了一個異步方法實現。

+0

感謝您的分享,我現在嘗試。 – BlueSky 2012-04-08 05:26:25

+0

您的解決方案已成功完成,謝謝。 – BlueSky 2012-04-08 07:51:37

+0

這裏說它無法找到類ChannelBase。我不明白我可以如何在異步方法中使用它。謝謝! – cheeesus 2012-04-16 11:36:14

0

我想你可能會在這裏容易混淆的名詞 - ChannelFactory通用類型,而不是一個動態

根據MonoTouch文檔,雖然有limitations to the Generics support in MonoTouch,ChannelFactory 應該在這裏沒關係。

您是否嘗試過使用ChannelFactory?

+0

是的,我試過使用ChannelFactory,我已經發布了上面的代碼,請參考,謝謝。 – BlueSky 2012-04-07 13:50:32

相關問題