异步 Web 服务设计模式
当编写连接到 WCF Web 服务的 Silverlight 应用程序时,我们在使用 Web 服务时面临的唯一选择是对 WS 接口进行异步调用。
即,
WebService client = new WebService();
client.ServiceMethodCompleted += new EventHandler<Args>(client_Handler);
client.ServiceMethodAsync();
client.close()
...followed by
void client_Handler(object sender, Args e)
{
//Next step, possibly another method?
}
虽然我理解编写 Web 应用程序(安全网)时异步调用的原因,但如果编写的方法的每个步骤都依赖于 Web 服务调用的结果,那么应该使用哪种类型的设计模式?
例如,如果 Web 服务中有一个方法可以检查访问者的用户凭据,并且根据该用户的组执行某些操作。
public MyPage() //Constructor
{
CheckCredentialsAsync();
if(result.IsUserTypeA)
{
//something complex
}
else if(result.IsUserTypeB)
{
//something else complex
}
...etc
}
有没有一种方法可以在不使用由先前的异步调用完成事件触发的方法的“多米诺骨牌”设计的情况下完成此任务?如果有大量的客户端/服务交互,它似乎会变得混乱。
谢谢!
When writing a Silverlight app hooked up to a WCF Web Service, the only option we are presented with in using the Web Service is to make asynchronous calls to the WS interface.
i.e.
WebService client = new WebService();
client.ServiceMethodCompleted += new EventHandler<Args>(client_Handler);
client.ServiceMethodAsync();
client.close()
...followed by
void client_Handler(object sender, Args e)
{
//Next step, possibly another method?
}
While I understand the reason for asynchronous calls when writing webapps (safety net), what type of design pattern would one use if a method was written where each step was dependent on the result of the Web Service call?
For instance, if there was a method in the Web Service that checked the user credentials of the visitor, and depending on the group of that user, would perform some action.
public MyPage() //Constructor
{
CheckCredentialsAsync();
if(result.IsUserTypeA)
{
//something complex
}
else if(result.IsUserTypeB)
{
//something else complex
}
...etc
}
Is there a way to accomplish this without using a 'domino' design of methods triggered by the previous asynchronous calls completed event? It seems as though it can get messy if there is a lot of client/service interaction.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我所知道的此类模式的最佳建模是事件驱动的有限状态机。异步方法完成是事件,您的“复杂操作”是操作,您的 MyPage 实例是当前状态。然而,对于任何相当数量的状态和事件,FSM 都可能非常复杂,虽然可以通过编写更简单的 FSM 来以某种方式控制它们,但我无论如何都不会称这种模式直观且简单。
坦率地说,我通常更喜欢你描述的回调链。 “多米诺骨牌”效应并不一定很糟糕,一旦您编写了几个这样的模块,您就掌握了它的窍门。它的复杂性基本上是由“复杂的东西”块中可能的执行分支的数量驱动的。在同步路径中,您可能有一个 if 分支,在异步路径中,您可能有两个单独的回调。需要输入更多代码,但不一定更难理解。 “更多代码”部分可以通过将 coe 适当工厂化为助手来处理。
我认为虽然我没有使用 Silverlight 类,但我的经验主要围绕 WebRequest、SqlClient 和 Stream 操作异步行为。最后,我发现最复杂的部分是错误处理的分割和资源所有权的分割,因为
using
模式对于异步来说不太有用。The best modeling I know for such patterns is event driven Finite State Machine. Async methods completion are events and your 'complex operations' are actions, your MyPage instance is current state. However FSM can be quite hairy for any fair number of states and events, and while they can be somehow kept in check by composing simpler FSMs, I would not call this pattern intuitive and easy by any stretch.
Frankly I often prefer the chain of callback you describe. The 'domino' effect is not necesarily bad, once you get to write a couple of modules like this you get the hang of it. Its complexity is basically driven by the number of possible execution branches in the 'something complex' blocks. Where in the synchrnous path you'd have an if branch, in the asynchronous path you'd likely have two separate callbacks. Is more code to type, but is not necesarily more difficult to comprehend. And the 'more code' part can be taken care with proper factory of the coe into helpers.
I reckon though that I did not work with the Silverlight classes, my experience is mostly around the WebRequest, SqlClient and Stream operations async behavior. In the end, the most complicated part I find to be the split of the error handling and the split of resource ownership, since the
using
pattern is far less usefull with async.如果您不想将回调链接在一起,请查看 Jeffrey Richter 的 AsyncEnumerator:
http://www.wintellect.com/PowerThreading.aspx
它也支持 Silverlight。
If you don't want to chain callbacks together, check out Jeffrey Richter's AsyncEnumerator:
http://www.wintellect.com/PowerThreading.aspx
It supports Silverlight too.
我同意你的观点:
看着长长的多米诺骨牌链是很难看的。它使代码变得混乱,因为(无休止的)调用列表和列表。页面中的回调不一定向其他开发人员传达给定系列是任何单个集合的一部分的信息。这就是为什么我会使用设计模式将这些调用包装到单个对象中。
如果您的多米诺骨牌调用链...
使用以前的调用数据:
我将使用 DECORATOR 设计模式将这些调用包装到一个对象中。使用装饰器模式的一个很好的例子是 STREAM 对象。
如果您的多米诺骨牌呼叫链...
不使用以前的呼叫数据:
我将使用 责任链< 将这些调用包装到一个对象中/strong> 设计模式。
但是
您可能使用或不使用其中之一的原因有很多。我只是想迎合您的具体情况。
以下是您的决定使用哪一个。
I AGREE WITH YOU:
Looking at a long domino-chain of calls is ugly. It confuses the code because the (endless) list of calls & callbacks in your page doesn't necessarily communicate to other developers that a given series is part of any single set. This is why I would wrap those calls into a single object using a design pattern.
If your domino-chain of calls...
USES THE PREVIOUS CALLS DATA:
I would wrap those calls into an object using DECORATOR deign pattern. A good example of something that uses the decorator pattern is a STREAM object.
If your domino-chain of calls...
DOES NOT USE PREVIOUS CALLS DATA:
I would wrap those calls into an object using CHAIN OF RESPONSIBILITY deign pattern.
HOWEVER
There are many reason why you might use or not use one-or-the-other. I am merely trying to cater to your specific situation.
Here is how you decide which one to use.