Шаблоны проектирования асинхронных веб-сервисов
При написании приложения Silverlight, подключенного к веб-службе WCF, единственная возможность, которую мы представляем при использовании веб-службы, - это выполнять асинхронные вызовы интерфейса 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?
}
Хотя я понимаю причину асинхронных вызовов при написании веб-приложений (сеть безопасности), какой тип шаблона дизайна можно использовать, если бы был написан метод, в котором каждый шаг зависел от результата вызова веб-службы?
Например, если бы в веб-службе был метод, который проверял учетные данные пользователя посетителя и, в зависимости от группы этого пользователя, выполнял бы какое-то действие.
public MyPage() //Constructor
{
CheckCredentialsAsync();
if(result.IsUserTypeA)
{
//something complex
}
else if(result.IsUserTypeB)
{
//something else complex
}
...etc
}
Есть ли способ сделать это без использования метода "домино", вызванного предыдущим событием завершения асинхронных вызовов? Кажется, что это может стать грязным, если есть много взаимодействия клиент / сервис.
Спасибо!
3 ответа
Лучшее моделирование, которое я знаю для таких шаблонов, - это конечный автомат, управляемый событиями. Завершение асинхронных методов - это события, а ваши "сложные операции" - действия, ваш экземпляр MyPage находится в текущем состоянии. Однако FSM может быть довольно проблематичным для любого значительного числа состояний и событий, и хотя их можно каким-то образом контролировать, составляя более простые FSM, я бы не стал называть этот шаблон интуитивно понятным и легким с любой точки зрения.
Честно говоря, я часто предпочитаю цепочку обратных вызовов, которые вы описываете. Эффект "домино" не обязательно плох, когда вы напишете пару таких модулей, вы получите его. Его сложность в основном определяется количеством возможных ветвей выполнения в "сложных объектах". Где в синхронном пути у вас будет ветвь if, в асинхронном пути вы, скорее всего, будете иметь два отдельных обратных вызова. Больше кода для ввода, но не обязательно сложнее для понимания. И часть "больше кода" может быть позаботилась о правильной фабрике коэффициентов в помощников.
Я считаю, что я не работал с классами Silverlight, мой опыт в основном связан с асинхронным поведением операций WebRequest, SqlClient и Stream. В конце концов, самой сложной частью я считаю разделение обработки ошибок и разделение владения ресурсами, поскольку using
шаблон гораздо менее полезен с асинхронным.
Если вы не хотите связывать обратные вызовы вместе, проверьте AsyncEnumerator Джеффри Рихтера: http://www.wintellect.com/PowerThreading.aspx
Он также поддерживает Silverlight.
Я С ТОБОЙ СОГЛАСЕН:
Глядя на длинную цепочку звонков в домино, уродливо. Это сбивает с толку код, потому что (бесконечный) список вызовов и обратных вызовов на вашей странице не обязательно сообщает другим разработчикам, что данная серия является частью какого-то одного набора. Вот почему я бы обернул эти вызовы в один объект, используя шаблон проектирования.
Если ваша домино-цепочка звонков...
Использует данные предыдущих звонков:
Я бы обернул эти вызовы в объект, используя шаблон DECORATOR deign. Хорошим примером того, что использует шаблон декоратора, является объект STREAM.
Если ваша домино-цепочка звонков...
НЕ ИСПОЛЬЗУЕТ ПРЕДЫДУЩИЕ ЗВОНКИ:
Я бы обернул эти вызовы в объект, используя схему сообразительности CHAIN OF ОТВЕТСТВЕННОСТИ.
ТЕМ НЕ МЕНИЕ
Есть много причин, по которым вы можете использовать или не использовать один или другой. Я просто пытаюсь удовлетворить вашу конкретную ситуацию. Вот как вы решаете, какой из них использовать.