|
|
|||||||||||||||||||||||||||||
|
Что нового для WCF в Visual Studio 2008Источник: max404
В Visual Studio 2008® и .NET Framework 3.5® появились новые средства и возможности поддержки, расширяющие функциональность среды Windows® Communication Foundation (WCF). Базовые возможности WCF 1.0 (выпущенной вместе с .NET Framework 3.0) не подверглись изменениям - они были расширены и дополнены.
Перекрестное нацеливание в .NET FrameworkВ предыдущих выпусках Visual Studio можно было создавать программы, нацеленные только на ту версию платформы .NET Framework, вместе с которой система Visual Studio и поставлялась. К примеру, в Visual Studio 2005 можно было создавать сборки только для .NET Framework 2.0. В действительности же разработчики сталкиваются с несколько иными задачами: им зачастую приходится поддерживать старые версии приложений, созданные в предыдущих версиях платформы .NET, а в то же время при обновлении приложений они уже работают с новой версией Visual Studio. Рис. 1 Свойство целевой версии платформы в Visual Studio 2008 Это значение используется только во время разработки; во время выполнения оно не играет никакой роли, поскольку версия среды (.NET 2.0 CLR) не изменилась. Значение, которые вы выберете, должно соответствовать самой старой версии платформы .NET Framework, на основании которой будет создаваться сборка. Для новых проектов по умолчанию задается версия .NET Framework 3.5. При добавлении ссылок возникают дополнительные сложности: если вы выбираете более старую версию в панели приложений, а ссылки создаете для сборки, созданной в более новой версии платформы, то Visual Studio 2008 выдает предупреждение, ссылка помечается как недействительная, и сборка не создается. Visual Studio 2008 не позволяет добавлять ссылки на сборки .NET Framework, требующие более высокой версии платформы, нежели та, в которой создается проект. Если вы добавите ссылку на проект, требующий более высокой версии платформы, Visual Studio 2008 сообщит вам о том, что возможен конфликт версий. Если же вы добавите ссылку путем непосредственного перехода к сборке, Visual Studio 2008 вас не станет останавливать.
Узел, предоставляемый WCFВ Visual Studio 2008 имеется готовый универсальный узел для размещения служб WcfSvcHost.exe. Он расположен в папке C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE. Чтобы удобнее было работать с ним, можно этот адрес добавить в системную переменную Path. WcfSvcHost - это простая программа командной строки, имеющая два параметра: путь к файлу сборки .NET, содержащей классы службы, и путь к файлу CONFIG узла, на котором размещаются службы. Например так: WcfSvcHost.exe /service:MyService.dll /config:App.config Сборка службы может представлять собой сборку библиотеки классов (DLL) или сборку приложения (EXE). Узел WcfSvcHost запустит новый процесс, в котором будут автоматически размещаться все классы, перечисленные в файле CONFIG в разделе служб. Стоит отметить, что классы служб, равно как и контракты служб и данных, не обязательно должны быть открытыми - это могут быть внутренни классы. Кроме того, при саморазмещении службам не обязательно предоставлять метаданные, но в случае необходимости они могут это делать. Рис. 2 Список WcfSvcHost Services В этом же окне отображается состояние службы и адрес ее метаданных - его можно скопировать в буфер, и использовать, к примеру, для добавления ссылки на службу. Если закрыть окно WcfSvcHost, то оно просто свернется в значок в области уведомлений. WcfSvcHost.exe /service:MyService.dll /config:App.config /client:MyClient.exe /clientArgs:123,ABC Эта функция может использоваться при автоматическом тестировании и в простейших сценариях развертывания для обеспечения запуска обеих частей системы - и размещающего узла, и клиента.
Тестовый клиент, предоставляемый WCFКроме узла для размещения служб в Visual Studio 2008 имеется универсальный тестовый клиент, позволяющий выполнять простейшее тестирование операций большинства служб. При стандартной установке тестовый клиент, WcfTestClient.exe, располагается в папке C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE. Ему требется единственный аргумент командной строки с указанием адреса метаданных службы, которую вы намерены тестировать: WcfTestClient.exe http://localhost:9000/ В качестве значения аргумента можно указать любой адрес метаданных, к примеру HTTP-GET, или конечную точку метаданных с доступом по пртоколу HTTP, TCP или IPC (именованные каналы). Можно указывать сразе несколько адресов: WcfTestClient.exe http://localhost:8000/ net.tcp://localhost:9000/MEX Клиент WcfTestClient - это приложение Windows Forms 3.5 (см. рис. 3). Дерево в левой части содержит тестируемые службы и соответствующие конечные точки. Вы можете открыть контракт любой конечной точки и выбрать операцию. Информация, связанная с подобным вызовом, отображается на вкладке в правой панели. В качестве примера можно привести элементарный контракт и реализацию, представленные на рис. 4. [ServiceContract] interface IMyContract { [OperationContract] string MyMethod(int someNumber,string someText); } class MyService : IMyContract { public string MyMethod(int someNumber,string someText) { return "Hello"; } }
Рис. 3 Использование WcfTestClient На вкладке методов, в разделе Request (Запрос) указывается целочисленное значение и строка, выступающие в роли параметров операции (см. рис. 3). Когда вы нажмете кнопку Invoke (Вызвать), будет выполнен вызов службы, а в разделе Response (Ответ) появятся возвращенные значения или выходные параметры. Если операция является односторонней, клиент WcfTestClient уведомит об успешном выполнении операции. В случае исключения появится сообщение с информацией о нем, и вам будет предложено выполнить повторный вызов. Рис. 5 Указание длины и значений массива [OperationContract] bool ProcessNumbers(int[] numbers На панели Response также будут указаны возвращенные составные значения или выходные параметры. Здесь мы сталкиваемся с определенным недостатком клиента WcfTestClient: чтобы протестировать другую службу, приходится закрывать клиент, менять аргументы командной строки и снова запускать его. Было бы удобнее иметь возможность указывать адрес службы и в графическом интерфейсе тоже. WcfSvcHost.exe /service:MyService.dll /config:App.config /client:WcfTestClient.exe /clientArgs:http://localhost:9000/ При использовании узла WcfSvcHost указывать аргументы метаданных необязательно. По умолчанию узел WcfSvcHost передает в указанное клиенткое приложение адреса метаданных, прописанные в файле CONFIG размещаемой службы. Указывать адреса явным образом нужно, только если они не указаны в файле CONFIG или если вы хотите, чтобы тестовый клиент использовал другие адреса. Если в файле CONFIG указано несколько конечных точек метаданных для выбранной службы, то использоваться они будут в следующем порядке: HTTP, TCP, IPC, HTTP-GET. Описанные этапы можно включить в Visual Studio 2008 для упрощения процедур размещения и тестирования служб. Чтобы это сделать, нужно указать WcfSvcHost.exe в качестве запускаемой программы (вместе с файлом CONFIG), а WcfTestClient.exe - в качестве клиента.
Библиотеки служб в WCFВ качестве одно из функций целевой платформы Visual Studio 2008 предлагает несколько новых шаблонов проектов WCF. В диалоговом окне New Project (Новый проект) есть поле со списком, в котором можно указать, для какой версии платформы проект создается (2.0, 3.0 или 3.5) - см. рис. 6. Рис. 6 Шаблоны проектов WCF Если выбрать Framework 2.0, новые шаблоны доступны не будут. Для Framework 3.0 появился новый шаблон под названием WCF Service Library (библиотека служб WCF). Этот проект представляет собой всего навсего готовый вариант использования узла WcfSvcHost и клиента WcfTestClient. По сути своей он весьма близок к тем методам, которые были описаны выше (при сочетании обоих компонентов). Если вы используете проект WCF Service Library, то ни указывать WcfSvcHost.exe в качестве выполняемого приложения, ни задавать файл CONFIG не нужно, поскольку в файле проекта есть элемент ProjectTypeGuids, предназначенный для библиотеки служб WCF.
Добавление ссылки на службуРасширения Visual Studio 2005 для .NET Framework 3.0 обеспечивают базовые возможности добавления ссылок на службы WCF. Многие дополнительные функции SvcUtil в них отсутствуют. В Visual Studio 2008 появилась новое диалоговое окно добавления ссылок на службы (см. рис. 7). Рис. 7 Добавление диалога ссылки на службу Чтобы открыть окно в проекте, нужно щелкнуть правой кнопкой мыши рабочую область проекта в обозревателе решения и в контектсном меню выбрать пункт Add Service Reference (Добавить ссылку на службу). При этом проект должен быть создан для .NET Framework 3.0 или более поздных версий. Рис. 8 Дополнительные параметры ссылки на службу Флажок Generate asynchronous operations (Создать асинхронные операции) для каждой операции импортированного контракта добавляет пару элементов Begin<операция> и End<операция>, тем самым позволяя клиентам выполнять асинхронные вызовы рабочих потоков, а впоследствии синхронизировать результаты операции либо путем обратного вызова, либо путем блокировки завершения. К примеру, рассмотрим следующее определение контракта: [ServiceContract] interface ICalculator { [OperationContract] int Add(int number1,int number2); } Импортированный контракт показан на рис. 9. [ServiceContract] interface ICalculator { [OperationContract] int Add(int number1,int number2); [OperationContract(AsyncPattern = true)] IAsyncResult BeginAdd(int number1,int number2, AsyncCallback callback,object asyncState); int EndAdd(IAsyncResult result); //Rest of the methods } Соответствующих клиентский код для асинхронного вызова будет выглядеть следующим образом: CalculatorClient proxy = new CalculatorClient(); int sum; AsyncCallback completion = (result)=> { sum = proxy.EndAdd(result); Debug.Assert(sum == 5); proxy.Close(); }; proxy.BeginAdd(2,3,completion,null); Эти методы можно использовать как есть, однако обратный вызов в методе Begin<операция> обращается к потоку из пула потоков. Это приводит к возникновению серьезной проблемы в том случае, если обратный вызов используется для доступа к ресурсам, связанным с определенным потоком или потоками. Классическим примером является приложение Windows Forms (или WPF), которое выполняет длительный асинхронный вызов службы (чтобы не блокировать пользовательский интерфейс), а затем пытается обновить интерфейс, добавив в него результаты вызова. Использовать метод Begin<операция> недопустимо, поскольку только поток интерфейса пользователя может обновлять интерфейс. Для решения подобных проблем был расширен базовый класс ClientBase<T>: в него был добавлен метод InvokeAsync, получающий контекст синхронизации от клиента и использующий его для обратного вызова при завершении операции, как показано на рис. 10. public abstract class ClientBase<T> : ... { protected delegate IAsyncResult BeginOperationDelegate( object[] inValues,AsyncCallback asyncCallback,object state); protected delegate object[] EndOperationDelegate(IAsyncResult result); //Picks up sync context used for completion callback protected void InvokeAsync(BeginOperationDelegate beginOpDelegate, object[] inValues, EndOperationDelegate endOpDelegate, SendOrPostCallback opCompletedCallback, object userState) {} //More members } В классе ClientBase<T> также имеется вспомогательный класс аргументов события и два выделенных делегата, которые используются для начала и завершения асинхронного вызова. Созданный класс прокси (производный от ClientBase<T>) задействует упомянутые базовые функции. Проски получает открытое событие <операция>Completed, в котором используется сильно типизированный класс аргументов события, непосредственно связанный с результатами выполнения асинхронного метода, и два метода <операция>Async, используемые для асинхронного распределения вызова: partial class AddCompletedEventArgs : AsyncCompletedEventArgs { public int Result {get;} } class CalculatorClient : ClientBase<ICalculator>,ICalculator { public event EventHandler<AddCompletedEventArgs> AddCompleted; public void AddAsync(int number1,int number2,object userState); public void AddAsync(int number1,int number2); //Rest of the proxy } Клиент также может подписать обработчик событий на событие <operation>Completed, чтобы он вызывался по завершении операции. Главная разница в использовании между методами <операция>Async и Begin<операция> состоит в том, что методы <операция>Async получают контекст синхронизации от клиента и вызывают событие <операция>Completed для данного контекста синхронизации, как показано на рис. 11. partial class CalculatorForm : Form { CalculatorClient m_Proxy; public MyClient() { InitializeComponent(); m_Proxy = new CalculatorClient(); m_Proxy.AddCompleted += OnAddCompleted; } void CallAsync(object sender,EventArgs args) { m_Proxy.AddAsync(2,3); //Sync context picked up here } //Called on the UI thread void OnAddCompleted(object sender,AddCompletedEventArgs args) { Text = "Sum = " + args.Result; } } Поле со списком Collection type (Тип коллекции) позволяет указать способ представления клиенту отдельных видов коллекций и массивов, существующих в метаданных службы. К примеру, если служба возвращает коллекцию IEnumerable<T>, IList<T> или ICollection<T>, по умолчанию прокси представляет ее как массив. В качестве примера можно привести следующий вариант работы на стороне службы: [OperationContract] IEnumerable<int> GetNumbers(); Эта коллекция будет представлена на прокси в следующем виде: [OperationContract] int[] GetNumbers(); Однако Visual Studio 2008 можно настроить так, чтобы использовались другие коллекции: BindingList для привязок, List<T>, Collection, LinkedList<T> и т. д. Если преобразование представляется возможным, прокси будет использовать вместо массива требуемый тип коллекции: [OperationContract] List<int> GetNumbers(); Аналогичная функция используется для словарей. Обычно служба возвращает сериализуемый словарь, подобный следующему: [Serializable] class MyDictionary<K,T> : IDictionary<K,T> {...} [OperationContract] MyDictionary<int,string> GetDictionary(); Затем класс прокси представляется этот словарь в виде Dictionary<T,K> - это значение, установленное по умолчанию в поле со списком Dictionary collection type (Тип коллекции словаря): [OperationContract] Dictionary<int,string> GetDictionary(); Однако вы можете запросить и другие типы словарей, например SortedDictionary<T,K>, HashTable или ListDictionary - прокси будет их использовать, если это возможно: [OperationContract] SortedDictionary<int,string> GetDictionary(); Наиболее важной возможностью, предоставляемой новой функцией создания ссылок на службы является возможность обмениваться типами контрактов данных между сборками. В Visual Studio 2005, если клиент добавлял ссылки на две независимые службы, поддерживающие один и тот же контракт данных, он получал два отдельных, хотя и совпадающих, типа, представляющих один и тот же контракт. В Visual Studio 2008, если в какой-либо из сборок, на которые ссылается клиент, уже имеется тип контракта данных, совпадающий с типом контракта, указанным в метаданных службы, на которую создана ссылка, то по умолчанию повторно этот тип не импортируется. Следует еще раз подчеркнуть, что существующая ссылка на контракт данных должна существовать в другой сборке, а не в самом проекте клиента. Это ограничение будет снято в будущих выпусках Visual Studio. Пока что лучшим и наиболее очевидным решением является следующее: вы сводите все совместно используемые контракты данных к одной выделенной быблиотеке классов, и все клиенты ссылаются на эту сборку. Рис. 12 Папка ссылок на службу Вы в любой момент можете щедкнуть ссылку правой кнопкой мыши и выбрать пункт Update Service Reference (Обновить ссылку на службу), чтобы повторно создать прокси и обновить файл CONFIG для клиента. Это возможно, поскольку в элементе ссылки на службу кроме всего прочего содержится файл, хранящий исходный адрес метаданных.
Ссылки по теме
|
|