提问人:Tomáš Bezouška 提问时间:8/14/2012 更新时间:8/15/2012 访问量:1479
IObservable REST 客户端
IObservable REST Client
问:
我想编写一个库,该库可以与 Web 服务器通信,并将来自它的数据公开给世界其他地方。Web 服务器没什么特别的,它公开了几种 REST 方法,主要是 GET 和 POST。
由于我对 Reactive Extensions 比较陌生(但我已经喜欢它了),所以我寻求建议。我决定库的接口将公开 IObservables。但我不知道如何具体实现这一点。我想我有几个选择:
1)曝光。REST服务一次返回所有请求的数据是有道理的。用户调用 Subscribe(),只推送一个 IEnumerable,调用 OnDone。因此,需要多次调用 Subscribe()。IObservable<IEnumerable<T>>
2)曝光。我想在某些情况下可能是一个不错的选择。Subscribe() 只会被调用一次,要获取其他数据,会有 Refresh() 或 NextPage() (...) 方法将更多数据获取到流中。(那么它可能不是一个属性,IObservable<T>
IObservable<T> GetResource...
IObservable<T> Resource { get; }
3)忘记Rx,通过事件以老式的方式做(最糟糕的事情IMO)
4) 其他方式?
有这方面的经验吗?我关心的是刷新(要求新数据)、分页、组合结果以及通常具有良好的可维护设计。
谢谢你的任何建议
答:
你在这里结合了两个问题,确实应该分开解决。
首先是你的代码从其他来源获取数据。第二种方法是在有新数据可用时将该数据发布给相关方。
关于第一个,反应式扩展无济于事。您在这里关心的是按时间间隔获取数据;它必须是一个定时间隔,因为在代码中调用 REST 服务时,没有回调,没有服务可以调用的挂钩。
如果从外部服务对代码进行了某种回调,则可以将其包装在一些 IObservable<T>
实现中,然后您可以订阅并对其执行操作(实际上只是转发订阅)。
将反应式扩展用于第一个问题的唯一方法是在 Observable
类上使用静态 Timer
方法启动计时器。
对于第二个问题(在您拥有数据并想要通知订阅者之后),您绝对可以并且应该使用实现来通知订阅者。IObservable<T>
在这种情况下,我强烈建议您不要尝试偏离接口上 Subscribe
方法的意图。您应该公开一个方法,该方法将为您提供任何人都可以订阅的方法(在调用之前是热的还是冷的由您决定),并通过调用返回的 IDisposable
接口实现上的 Dispose
方法取消订阅。IObservable<T>
IObservable<T>
IObservable<T>
Subscribe
Subscribe
这样,您的客户就可以获取 ,订阅他们想要的通知,然后在完成后取消订阅。IObservable<T>
评论
IObservable<T>
我建议使用以下界面:
public interface IRestService
{
IObservable<T> GetResources<T>();
}
这种选择背后有很多原因。
公开 将反应式与交互式(或可观察对象与枚举对象)混合在一起,并会强制查询调用,或者更糟糕的是,构造基本查询。最好更好地保持查询和订阅代码的干净。IObservable<IEnumerable<T>>
.ToObservable()
.ToEnumerable()
SelectMany
现在,您建议使用 an 您只需订阅一次,并且需要 or 调用才能将更多数据获取到流中。这不是一个好主意。相反,您应该认为单个订阅将返回单个 REST 调用的所有结果,然后调用 .如果要调用新的 REST 调用,只需再次订阅即可。IObservable<T>
Refresh
NextPage
OnComplete
此外,代码中未明确表达单个订阅调用的语义。因此,您需要考虑维护代码。当你将来查看代码时,你可能会认为语义是什么?我建议单个订阅的语义更有可能映射到单个 REST 调用。否则,您的代码可能会更加混乱。
更进一步,您应该避免使用单个订阅模型,因为如果抛出任何异常,那么您的可观察对象就完成了,当然,调用 Web 服务可能非常容易出错。如果多订阅模型出现错误,则可以更轻松地恢复。
我也会避免,因为它建议某种“固定”值,相反,它更动态 - 换句话说,每个调用可能会给你不同的值。最好调用方法而不是属性。IObservable<T> Resources { get; }
GetResources
Resources
一些,底线,我会有一个抽象到你的底层REST服务的单个调用。IObservable<T>
评论
.OnNext(Default.Unit)
评论