Mar*_* Ba 7 c# wcf remoteobject protobuf-net nettcpbinding
首先,这不是IEnumerable <T>的副本作为WCF方法的返回类型,我想我明白WCF架构只允许传输可以填充到消息中的具体类型.
其次,我们的设置不是一般服务,而是通过C#+ WCF + NetTcpBinding + Protobuf(仅)连接一组专有应用程序,因此我们可能有更多空间来处理某些需要更具约束力中性的技巧.
第三,提出不同的RPC或消息框架既不是我的地方,也不是这个问题.
出于这个问题的目的,"IEnumerable语义"是:
List
或相似.foreach
并完成它.在本地程序集中,C#接口看起来像这样:
interface IStuffProvider {
IEnumerable<Stuff> GetItems(); // may open large file or access database
}
Run Code Online (Sandbox Code Playgroud)
您无法将其直接映射到WCF服务.可能达到相同效果的东西可能如下所示:
[ServiceContract(SessionMode = SessionMode.Required)]
interface IStuffService {
[OperationContract]
void Reset(); // may open large file or access database
[OperationContract]
List<Stuff> GetNext(); // return next batch of items (empty list if no more available)
}
Run Code Online (Sandbox Code Playgroud)
当然,使用IStuffService
将比a IStuffProvider
和添加到混合中更容易出错,而不是许多使用场景将涉及在同一台机器上同时使用服务和客户端,因此对于"用户代码",要意识到这一点并不是非常重要的.涉及"网络",用户代码只对简单的界面感兴趣.
一种选择当然是拥有一个客户端接口包装器实现,它公开IStuffProvider
并内部转发和使用IStuffService
.然而,现在看来,这真的希望没有必须保持两个接口,一个用于用户代码,一个纯粹为WCF通信,特别是因为这些应用程序都是严格反正耦合的,因此额外的抽象似乎只是开销.
我们在这里使用WCF有哪些选择?
请注意,在阅读之后,Streamed Binding似乎是一个糟糕的解决方案,因为我仍然需要客户端上的包装器,并且服务接口会变得更加复杂,在我的情况下没有真正的好处:我不需要最大二进制转移效率,我想好的实施+维护效率.
我最终所做的是:
a) OO接口 IStuffProvider
如上,成员GetLines()
如上。
b) WCF 服务接口(及其实现)实现如下访问模式:
[OperationContract]
ReadToken StartReadingLines(...);
[OperationContract]
// return next batch of items (empty list if no more available)
List<Stuff> ReadNextLines(ReadToken readToken);
[OperationContract]
void FinishReadingLines(ReadToken readToken);
Run Code Online (Sandbox Code Playgroud)
c) 客户端通过代理类访问服务,该代理类实现IStuffProvider
并对函数的调用映射GetLines()
到上述三个函数:
// implementation in the proxy class:
public IEnumerable<Stuff> GetLines()
{
var readToken = _dataService.StartReadingLines(...);
try {
for (List<Stuff> lines = _dataService.ReadNextLines(readToken); lines.Count > 0; lines = _dataService.ReadNextLines(readToken)) {
foreach (var line in lines) {
yield return line;
}
}
} finally {
_dataService.FinishReadingLines(readToken);
}
}
Run Code Online (Sandbox Code Playgroud)