监守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中不支持动态代理代码生成。 覆盖此方法或调用者返回特定的客户端代理实例
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:我添加了一个异步方法实现。
我想你可能会在这里容易混淆的名词- 的ChannelFactory是一个通用的类型,而不是动态的 。
据MonoTouch的文档,虽然有限制在MonoTouch中的泛型支持 ,的ChannelFactory 应该没问题在这里。
你是否尝试过使用的ChannelFactory?