Я работаю над проектом, который должен создать XML с определенными данными в определенном формате, отправить его сторонней службе и затем обработать результат. Третья функция здесь состоит в том, чтобы проверить как данные, так и формат XML, а затем создать кодифицированную строку ("штамп"), подтверждающую, что все соответствует запросам. Затем эта марка должна быть добавлена в исходный XML и храниться в базе данных.
Теперь третья сторона по-прежнему должна быть выбрана, поэтому я должен создать свой проект таким образом, чтобы он работал (до сих пор) двумя различными веб-сервисами до выпуска, с возможностью добавления другого и после выпуска изменения Выбранный. Хотя конечный результат один и тот же ("тиснение" XML), каждый веб-сервис выполняет разные действия, например, возвращает только строку штампа, в то время как другая возвращает XML с включенной печатью, а ожидающий возвращает массив байтов zip файл, содержащий XML (я не знаю, кто сказал им, что это хорошая идея, но meh, эта другая история)
Имея это в виду, я решил создать статический класс, который обертывает вызовы веб-сервисов (один метод для каждой веб-службы). Все эти методы получают XML и возвращают либо "штампованный" XML, либо XML с кодом ошибки и сообщением в случае, если что-то пошло не так. Класс, который обрабатывает данные, должен только создать необходимый XML, вызвать один из этих методов и обработать результат.
Пока это выглядит примерно так:
public class EDocument
{
//This class handles all the data that will be included in the XML
public void Stamp()
{
//Here the XML string is created, sent to the correspondig third-party web service, and processed back
string xmlString;
//code to create the XML
//...
//If needed, I only have to change this line to call the corresponding method
WebServiceCalls.MainWebServiceCall stamper = WebServiceCalls.FirstServiceCall;
stamper.BeginInvoke(xmlString, StampCallback, null);
}
public void StampCallback(IAsyncResult ar)
{
AsyncResult result = (AsyncResult)ar;
WebServiceCalls.MainWebServiceCall caller = (WebServiceCalls.MainWebServiceCall)result.AsyncDelegate;
string response = caller.EndInvoke(ar);
//Call another async method to save to database the stamp, create the XML file, e-mail and store it, and notify the results...
//or create the exception with the error details and raise event here to notify the error
}
}
Веб-службы звонков...
public static class WebServiceCalls
{
//Here I'll put the necessary web service calls. In the end there will be only one,
//but if on future the web service changes, a method with the same signature will be created here
//replacing the previous one
public delegate string MainWebServiceCall(string XmlData);
public static string FirstServiceCall(string XmlData)
{
FirstWebService firstWs = new FirstWebService();
string serviceResult = firstWs.Stamp(XmlData); //This returns only the stamp string
//Check the result, add the stamp to the original XML or create the error XML, and return...
return serviceResult;
}
public static string SecondServiceCall(string XmlData)
{
SecondWebService secondWs = new SecondWebService();
string serviceResult = secondWs.Stamp(XmlData); //This returns the XML with the stamp already added
//Check the result, create the error XML if something went wrong, and return...
return serviceResult;
}
public static string ThirdServiceCall(string XmlData)
{
ThirdWebService thirdWs = new ThirdWebService();
string serviceResultString;
byte[] serviceResult = thirdWs.Stamp(XmlData); //This (sigh) returns the byte array of a ZIP file...
//Unzip the file, check the result, create the corresponding XML and return...
return serviceResultString;
}
}
Но потом он ударил меня... Хотя я буду асинхронно вызывать методы обёртки, метод веб-службы все равно будет вызываться синхронно.
Вопрос в том, каковы недостатки этого? следует ли я вместо этого асинхронно обращаться к веб-службе по каждому методу вызова, обрабатывать обратный вызов, поднять уведомление, ухватить его в классе Edocument, обработать результат и поднять его соответствующее событие? Разве это не осложняло бы рассмотрение возможных будущих изменений этого проекта?
Или это общий неправильный подход к проблеме?
Имейте в виду, что это С# 4.0, поэтому (к сожалению) асинхронный ожидания выходит за рамки.
Вы не используете async IO вообще. Delegate.BeginInvoke
использует пул потоков. В серверных приложениях это практически повредит практически во всех ситуациях. Async IO не имеет потоков.
Используйте синхронный код или асинхронный ввод-вывод.
Кажется, вы думаете, что асинхронное обращение к веб-сервису, которое внутренне синхронно (или наоборот), может иметь недостаток. Это не тот случай. Ни одна из сторон не может даже сказать, как реализуется другая. Переход на асинхронный уровень в определенном уровне влияет только на этот уровень.