MonoTouch的/ WCF:如何消耗不SvcUtil工具WCF服务MonoTouch的/ WCF

2019-05-13 11:31发布

监守MonoTouch的编译为本机代码,所以它有一定的局限性,诸如动态调用是不允许的。

但我在.net中有很多类,我用的ChannelFactory动态调用WCF服务:新的ChannelFactory(myBinding,myEndpoint); 现在,在MonoTouch的时候应该使用slsvcutil生成WCF代理类,但slsvcutil产生很多不必要的额外代码(巨大),并使得消费者很难进行单元测试,由于与通过ClientBase类的WCF基础设施高耦合。

是否有除的ChannelFactory一个更好的解决方案? 我宁愿手动编写代码,有超过服务是如何被调用,如的ChannelFactory更多的控制。

==========

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

// ==>它抛出异常:MonoTouch中不支持动态代理代码生成。 覆盖此方法或调用者返回特定的客户端代理实例

Answer 1:

ChannelFactory<T>具有虚拟方法CreateChannel() 如果不重写,它使用动态代码生成,从而未能对MonoTouch的。

解决的办法是将其覆盖,并提供自己的编译时执行。

下面是我的一个老服务实现,至少曾经在MonoTouch的工作。 仅在iOS上的第一个链接了所有版本,第二个建立(允许动态的生成机制,仍然工作在Windows上) - 我把它分解成2部分类。
我已经剥离下来到只包含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:我添加了一个异步方法实现。



Answer 2:

我想你可能会在这里容易混淆的名词- 的ChannelFactory是一个通用的类型,而不是动态的

据MonoTouch的文档,虽然有限制在MonoTouch中的泛型支持 ,的ChannelFactory 应该没问题在这里。

你是否尝试过使用的ChannelFactory?



文章来源: Monotouch/WCF: How to consume the wcf service without svcutil