Примечание автора: эта статья была написана в районе 2008 года, и, скорее всего, она уже морально устарела. Однако, судя по отзывам, все еще кому-то полезна. Статья разделена на несколько частей.
Введение
Эта статья для тех, кого заинтересовала технология WCF, и те преимущества, которые она дает разработчику распределенных и сервис-ориентированных приложений.
Сегодня я расскажу о том, как создать простейшую WCF-службу. Для примера будем использовать классический вариант — калькулятор.
Создание службы
Для создания нашего приложения мы будем использовать Visual Studio 2008. Итак, вызовем диалоговое окно создания нового проекта и выбираем шаблон проекта под названием «WCF Service Library» и дадим ему имя «WcfCalcService».
Проект сейчас состоит из трех основных файлов. Посмотрим, за что каждый из них отвечает.
1. App.config — файл конфигурации приложения. В этом файле также находятся настройки службы;
2. IService1.cs — файл с интерфейсом (контрактом) службы;
3. Service1.cs — файл с классом, реализующим интерфейс (т.е. функционал службы).
Контракт службы
Изначально VS открывает перед нами файл IService1.cs. Это вполне оправдано, ведь разработка любой службы должна начинаться с определения того, что же она все-таки будет делать. Поменяем имя интерфейса на ICalcService (а также переименуем файл в ICalcService.cs). Заметьте, что перед объявлением интерфейса стоит атрибут ServiceContract. Это-то как раз и означает, что данный интерфейс является контрактом WCF-службы.
Примечание:
В комментарии перед кодом интерфейса написано:
// NOTE: If you change the interface name “IService1″ here, you must also update the reference to “IService1″ in App.config.
Что означает: «Если вы измените имя интерфейса «IService1» здесь, вам также нужно будет обновить ссылку на «IService1» в файле App.config». Мы это сделаем чуть позже, а этот комментарий можно удалить.
Примечание:
Не забывайте пользоваться рефакторингом, чтобы везде, где в коде упоминается IService1, его имя заменилось на ICalcService.
Настало время определиться, что будет делать наш калькулятор. Для начала, пусть он складывает, вычитает, умножает и делит целые числа. Для того чтобы отразить это в коде, нужно удалить все автоматически созданное за нас студией содержимое интерфейса и вместо него добавить строки:
Примечание
Ниже описания интерфейса находится описание типаCompositeType, который VS создает для примера. Его можно удалить.
Итак, теперь файл ICalcService.cs выглядит следующим образом:
Вы, наверное, уже заметили, что мы нигде не описали типыCalcOperationResult и CalcOperationType. Этим мы сейчас и займемся — эти типы будут использоваться для обмена данными между клиентом и службой.
Примечание
В реальной жизни, используемые для обмена структуры данных, равно как и интерфейс службы, необходимо продумать заранее, исходя из поставленной задачи.
Вообще, я рекомендую все, используемые для обмена типы, выделять в отдельную сборку, особенно, если вам нужен еще и какой-то общий функционал этих типов. Существует еще один вариант — описать интерфейсы типов, а реализацию сделать различной на клиенте и сервере. Такой вариант хорош при создании более-менее больших и сложных систем. Есть и третья возможность. Студия, при создании ссылки на сервис (Service Reference, это мы рассмотрим подробнее в статье про создание клиентских приложений), автоматически скачивает метаданные (описание структуры и функционала сервиса в специальном формате — WSDL) и по ним генерирует все контрактные типы, но у этого подхода есть два минуса. Первый — у нас нет доступа к методам сгенерированного типа (VS их просто не создает). Второй — для автоматического создания ссылки на службу нужна работающая служба с открытыми метаданными. Это встречается очень редко, если вы хотите создать клиентское приложение для существующей чужой службы. Поэтому, думаю, моя точка зрения по этому вопросу вполне ясна.
Мы воспользуемся первым вариантом: создадим еще одну сборку, добавив в решение новый проект с шаблоном «ClassLibrary» и дав ему имя «CalcCommon».
Чтобы в нашей общей сборке были доступны атрибуты для контрактов, нужно добавить ссылку на сборку System.Runtime.Serialization (правой кнопкой по проекту — Add reference).
Теперь удалим из нового проекта все лишнее, создадим новый файл класса (для этого можно нажать сочетание клавиш Alt+Shift+C) и назовем его CalcOperationResult.cs. Так выглядит описание типа CalcOperationResult:
Атрибут DataContract говорит о том, что данный тип используется для описания контракта данных службы и будетсериализуемым специальным диспетчером сериализации (System.Runtime.Serialization.DataContractSerializer). Соответственно DataMember говорит, что данный член класса относится к описанию контракта данных и будет сериализован тем же DataContractSerializer’ом.
Создадим еще один файл, где опишем перечисление CalcOperationType:
Как видите, для описания перечисления так же используется атрибут DataContract. А вот для членов перечисления нужен специальный атрибут EnumMember. В противном случае все значения типа перечисления будут передаваться в виде строки.
Примечание
Не забывайте в список используемых модулей добавлять строку:
using System.Runtime.Serialization;
Отлично! Осталось подключить к проекту службы сборку CalcCommon (правой кнопкой по проекту — Add Reference — закладка Projects) и наш интерфейс полностью готов (не забываем про using CalcCommon).
Если Вы нашли ошибку, пожалуйcта выделите ее и нажмите Shift + E или нажмите здесь чтобы информировать меня. Спасибо.