zoukankan      html  css  js  c++  java
  • Monotouch/WCF: How to consume the wcf service without svcutil

    Becuase monotouch compile to native code, so it has some limitation such as dynamic invoke is not allowed.

    But I have a lot class in .net, that I use the ChannelFactory dynamic to invoke the wcf service: new ChannelFactory(myBinding, myEndpoint); Now in monotouch I should use the slsvcutil to generate the wcf proxy class, but the slsvcutil generate a lot of Unnecessary extra code (huge), and Makes consumers difficult to unit test, due to high coupling with the WCF infrastructure through the ClientBase class.

    Is there a better solution except the ChannelFactory? I would rather write the code manually, have more control over how services are invoked such as the ChannelFactory.

    ==========

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

    //==> It throw exception: MonoTouch does not support dynamic proxy code generation. Override this method or its caller to return specific client proxy instance

    ChannelFactory<T> has a virtual method CreateChannel(). If this is not overridden, it uses dynamic code generation, which fails on MonoTouch.

    The solution is to override it and provide your own compile-time implementation.

    Below is an old service implementation of mine that at least used to work on MonoTouch. I split it up into 2 partial classes - the first one being linked in all builds, the 2nd only in the iOS builds (allowing the dynamic generation mechanism to still work on windows).
    I've stripped it down to only contain 1 service call.

    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 which executes the calls via reflection)

    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);
            }
    
        }
    }
    

    EDIT: I just tested this with the latest MT (5.2) - it no longer needs all that extra boiler plate I had in there before, just the CreateChannel() override. I've cleaned up the sample code to match.

    EDIT2: I added an async method implementation.

    from:http://stackoverflow.com/questions/10054581/monotouch-wcf-how-to-consume-the-wcf-service-without-svcutil

  • 相关阅读:
    IOS中常见的Operation —— NSOperation
    动态语言,别再说不
    CoreImage的使用及常见滤镜工具(一)
    【iOS】用Layer创建一个三维模型以及拖动
    前端基础-html、css
    mysql数据库—索引
    mysql数据库—用户管理、pymysql模块
    mysql数据库—函数、数据备份、流程控制
    mysql数据库基本操作2
    mysql数据库—事务、存储过程
  • 原文地址:https://www.cnblogs.com/zjoch/p/4603184.html
Copyright © 2011-2022 走看看