Monotouch/WCF:如何在不使用svcutil的情况下使用wcf服务 [英] Monotouch/WCF: How to consume the wcf service without svcutil

查看:118
本文介绍了Monotouch/WCF:如何在不使用svcutil的情况下使用wcf服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于monotouch可以编译为本机代码,因此它具有一定的局限性,例如不允许动态调用.

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

但是.net中有很多类,我使用ChannelFactory动态调用wcf服务:new ChannelFactory(myBinding,myEndpoint);现在,在monotouch中,我应该使用slsvcutil来生成wcf代理类,但是slsvcutil会生成许多不必要的额外代码(巨大),并且由于与ClientBase类之间的WCF基础结构高度耦合,使得使用者难以进行单元测试.

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.

除了ChannelFactory之外,还有更好的解决方案吗?我宁愿手动编写代码,也可以更好地控制如何调用服务,例如ChannelFactory.

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

//==>引发异常:MonoTouch不支持动态代理代码生成.覆盖此方法或其调用方以返回特定的客户端代理实例

//==> 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>具有虚拟方法CreateChannel().如果不重写,它将使用动态代码生成,这在MonoTouch上将失败.

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.

以下是我的旧服务实现,至少曾经在MonoTouch上使用过.我将其分为2个局部类-第一个在所有内部版本中都链接在一起,第二个仅在iOS内部版本中链接(允许动态生成机制仍在Windows上运行).
我将其简化为仅包含1个服务调用.

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:

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通过反射执行调用)

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

    }
}

我刚刚使用最新的MT(5.2)进行了测试-它不再需要我之前拥有的所有额外样板,只需重写CreateChannel().我已经清理了示例代码以进行匹配.

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.

我添加了一个异步方法实现.

I added an async method implementation.

这篇关于Monotouch/WCF:如何在不使用svcutil的情况下使用wcf服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆