Титры к видео уроку - "Введение в WCF "

Ссылка на полный видео урок

Урок 1. Введение в WCF

Здравствуйте, меня зовут Александр Шевчук. Я сертифицированный тренер Microsoft, работаю в компании CyberBionic Systematics. Я рад вас приветствовать на информационном видео ресурсе для разработчиков программного обеспечения ITVDN. Тема данного урока «Введение в технологию Windows Communication Foundation».

Что такое Windows Communication Foundation? Windows Communication Foundation – это технология, которая предназначена для построения распределенных информационных, чаще всего корпоративных, систем. Это некий программный framework который используется для обмена данными между приложениями и этот framework входит в состав .NET Framework. До своего выпуска в декабре 2006 года в составе .NET Framework 3.0 WCF был известен под кодовым именем Indigo. По сути, WCF это множество классов, можно сказать множество типов входящих в состав Microsoft .NET Framework. Эти типы позволяют разработчикам создавать сервис ориентированные приложения. Логически WCF представляет собой набор конструкций, которые позволяют разработчикам быстро разрабатывать сервис ориентированные приложения. А что же представляет собой распределенное или сервис ориентированное приложение?

Обратите внимание на этот слайд. У нас на слайде имеется сервер и некие клиентские части. Если мы посмотрим на сторону сервера, мы увидим вот такие странные конструкции. Эти странные конструкции представляют собой сервисы – сервисы провайдер. А теперь посмотрим на клиентскую сторону. Здесь имеются похожие конструкции, но клиентские сервисы называются сервисы consumer. Обратите внимание, клиентский сервис consumer обращается к серверному сервису провайдеру с определенным запросом. Например, можно представить вот эту систему скайпом (Skype) или LifeMessenger, или ICQ, или каким-нибудь чат приложением. Например, у скайпа имеется свой сервер, на котором имеются определенные сервисы - сервис знакомств, сервис настроек и сервис передачи сообщений. Например, находятся два человека, которые общаются друг с другом в чате. Допустим, один человек это я. Я посылаю сообщение, и сервис передает мое сообщение моему собеседнику. А мой собеседник может производить какие-то настройки и просматривать какие-то изображения на сервисе знакомств. А вот у нас имеется неактивная часть приложения. Это тот человек, который вышел сейчас из скайпа, например. То есть логически он присутствует в системе, но сейчас эта часть является неактивной.

Перейдем к следующему слайду, который показывает что WCF это технология, которая полностью построена на базе .NET Framework. Она написана с использование языка С# и является частью .NET. Обратите внимание на этот слайд. Здесь представлен набор типов, которые входит в WCF, а также в Workflow, потому что это две тесно связанные технологии и уже детальней со всеми типами, которые входят в технологию WCF, мы познакомимся на протяжении курса.

Давайте посмотрим следующий слайд и расмотрим такое понятие как случайная архитектура. Корпоративные информационные системы часто состоят из набора несвязаных друг с другом приложений. Что это значит ? Представте что у нас есть некая CRM (client relationship management) система, ERP (enterprise resource planning) система и некая бугалтерская система. И плюс ко всему эти системы от разных производителей. Владельцу бизнеса требуется как-то консиледировать отчетности или требуется что бы данные из одной системы могли попадать в другую систему и так далее. Поэтому здесь следует подумать как же можно увязать например Microsoft Dynamics с , например, 1С бугалтерией. Для этого стоит создать набор сервисов которые будут обращатся к разным системам и как-то передавать между ними данные. Производители таких промежутачных приложений называются интеграторами – они интегрируют, то есть обьединяют, такие системы вместе. Приложение такого рода называются приложения уровня middleware. А такая архитектура состоящая из розрозненых систем называется случайной информационной архитектурой предприятия.

Давайте посмотрем следующий слайд где у нас выдвигается некое универсальное требование к бизнесу. Его можно сформулировать так – мне нужно что бы в приложении А были данные из приложения В. Такого рода требования называются связанностью. Какие бывают виды связаности? Бывают две формы связаности – приложение с приложением и приложение с предприятием. Что это значит ? Например, если связаность это некое универсальное требование к информационной системе в которой должен быть налажен процес обменна данными между разными частями системы, то мы понимает, что у предприятие есть информационная система состоящая из неких подсистем (CRM систем, ERP систем, систем бугалтерского учета и разных других) и получается что приложение с приложением нам понятно, что из CRM системы данные о клиентах попали в какою-то другую систему. А приложение с предприятием. Предприятие это уже некое физическое представление, части предприятие это склад, где стоят коробки, это автомобили, которые подьежают. И каким же образом приложение может взаимодействовать с коробкой ? Очень просто – на коробках могут находится баркоды, которые могут считыватся специальными устройствами и информация об этой коробке о завезенном товаре поступает в приложение, что бы не руками вводить, используя клавиатуру, а при помощи определенных устройств. Снова же мы видем, что связанность бывает двух видов (приложение с приложением и приложение с предприятием).

Теперь расмотрим еще один важный термин – SOA (Service Oriented Architecture), сервис-ориентированая архитектура. Сервис-ориентированая архитектура – это такая архитектура, которая основана на использовании сервисов. Посмотрим на определение. Сервис-ориентированая архитектура – это модульный подход к разработке програмного обеспечения, основанный на использовании сервисов (служб) со стандартизированными интерфейсами. Давайте разберем более детально этот момент. Модульный подход – это значит, что каждый сервис представляет собой некий независимый модуль, некий независимый компонент, который обладает каким-то своим интерфейсом взаимодействия с ним, он обладает некой автономностью. Автономность подразумивает в себе наличие некой функциональной полноты и самодостаточности для того что бы он мог находится где-то отдельно и мог выполнять небольшую задачу предназначеную только для него. Основанный на использовании сервисов (служб). Конечно же, модуль это отдельный некий програмный модуль, который находится на сервере, к которому обращаются клиенты со стандартизированы интерфейсами. Это значит что у модуля имеются четко определенный интерфейс взаимодействия с ним. Вы уже не можете попросить у него то, он не может сделать. Еще раз. Сервис-ориентированая архитектура, в первую очередь, это модульный подход к разработке програмного обеспечения, основанный на использовании сервисов (служб) со стандартизированными интерфейсами. А сервис-ориентированость – это тип архитектуры, при которой слабая связаность компонентов распределенный приложений обеспечивается по средствам использования сообщений и контрактов.

Теперь было бы хорошо расмотреть основные принципы SOA. Очень кратко, потому что на протяжении курса мы будем расматривать более детально каждый из этих принципов. Давайте посмотрим первый. Архитектура не привязана к определенной технологии. Конечно же у Вас может уже быть Ваша сложная информационная структура информационой системы предприятия, которая можеть быть построена с использованием сторонних технологий, но возможно Вам нехватает их возможностей и технология WCF предоставляет более расширеные возможности и Вас никто не заставляет брать и отказыватся от той информационой составляющей, от того ПО которое у Вас присутствует. Вы можете всего лишь внидрять WCF независимо разширяя уже существующие решение. Таким образом потихонечку переводя свои решения на WCF. Почему стоит переводить свои решения на WCF? WCF это очень удобная, мощная и функционально богатая технология, которая предоставляет гораздо больше возможностей чем все вместе взятые технологии стороних производителей. Об этом тоже мы будем говорить.

Второй пункт – независимость организиции системы от используемой вычислительной платформы (платформ). Понятно что WCF поддерживает работу с разными сервисами которые могут находится как на Windows платформе, так и на других платформах, благодоря тому, что WCF поддержует все необходимые протоколы и в WCF заложены такие возможности, которые позволяют общатся с сервисами сторонних производителей.

Третий пункт – независимость организации системы от применяемых языков программирования. Мы знаем что под платформу .NET можно писать програмы с использованием самых различных языков программирования и поэтому если мы можем писать приложение на Visual Basic, на C++, то мы можем свободно в таких приложениях использовать технологию WCF.

Следующий пункт – использование сервисов, независимых от конкретных приложений, с единообразными интерфейсами доступа к ним. Представте себе что у нас есть сервис, который позволяет подчитать нам курсы валют и с CRM систем, и с какого-то валютного калькулятора, и с игры, например, мы можем обращатся к этому сервису и считать курсы валют. Мы не привязываетмся только к какому-то одному типу приложений.

Следующий пункт – организация сервисов как слабо-связанных компонентов для постороения систем. Мы знаем, что имеется такое понятие как слабая-связонность и сильная-связность. Что такое связонность? Связонность – это мера независимости, это мера самостоятельности обьекта или компонента. И поэтому наши компоненты, наши сервисы должны быть слабо-связаны. А что такое сильная-связность ? Сильная-связность определяет меру функциональной полноты, меру самодостаточности компонента. Когда компонент обладает функциональной полнотой для того что бы выполнять свой заложеный в него род деятельности, что бы он как можно меньше обращался за помощью к другим компонентам. Так вот, организация сервисов как слабо-связанных компонентов для постороения систем. Архитектура диктует нам уже очень жестко, даже не так как в обьектно ориентированом программировании, а уже больше как в компонентно ориентированом программировании, что всетаки этот большой независимый обьект должен обладать слабой связанностью и желательно сильной связностью. Он должен как можно мение зависим от других компонентов и как можно более функционально полным. Но при этом важно, что бы мы руководствувались принципами необходиной достаточности.

Давайте мы посмотрим следующий слайд и посмотрим, где находится место слоя сервисов в обещей архитектуре приложения. Мы знаем что вся функциональность приложения распредиляется по функциональным областям, или как мы их называем – слои. Мы видем на этой диаграме, желтым цветом, помечен слой представления, где распологается класы и все типы которые относятся к построению user-интерфейса. Далее мы видим слой сервисов, он выделен. Здесь будут находится класы и типы, относящиеся к работы слоя сервисов. Ниже бизнес-слой, или как его еще называют – домен. Еще ниже слой доступа к данным. Потом мы видем, что слой сервисов обращается как к внешним системам, так и внешние системы могут обращатся к нашему слою сервисов, и мы уже из слоя сервисов обращаемся в бизнес-слой, тоесть в домен, где у нас и находятся те сущности, можно назвать их концептами, которые являются некими виртуальными выражениями сущностей проблемной среды предметной области. Далее мы видим слой сквозной функциональности. В Microsoft мы знаем, что этот слой представлен библиотекой Enterprise library. Если уже посмотреть на многослойную архитектуру то здесь вы видете где должен находится слой сервисов.

Все сервис ориентированые приложения называют приложения обмена сообщениями. И это правда, потому что мы видим, на этом слайде у нас имеются два сервиса. Сервис провайдер, справа, и сервис consumer слева. Обратите внимание, между ними нарисован конвер. Что это значит? Это сервис consumer, сервис потрибитель услуг, обращается с запросом к сервис провайдеру. Сервис провайдер обрабатывает его запрос и возвращает ответ. Но это очень образно. Расмотрим пример. Представте что сервис провайдер это простейший калькулятор который умеет складывать числа. Сервис consumer, я, хочет узнать, сколько будет 2+2. Я беру, помешаю в конверт запрос «Сколько будет 2+2?» и отправляю на сервис провайдер. Сервис провайдер открывает мой конверт, достает эту задачу запускает какой-то метод добавления, помещает одну двойку и вторую двойку вкачестве аргументов, вычисляет, получает четверку, берет конверт, ложит результат вычисления в конверт и отправляет его мне. Можно увидеть, на слайде идут вде стрелочки с запросом, к сервис провайдеру и к сервис consumer. Вот по такому принципу и устроены все системы обмена сообщениями и на самом деле, все сервисы работают именно по такому принципу. Сейчас мы конечно видем какие-то странные состовляющие сервисов, мы их скоро расмотрим.

Следующий важный момент, который стоит расмотреть, это конфликты форматов сообщений. Мы понимаем, что все сервисы обмениваются друг с другом сообщениями. Представьте себе, что у нас имеются платформы от разных производителей. Вот у нас имеются сервисы Microsoft, сервисы Sun Microsystems и сервисы IBM. Мы видем, что на каждой стороне есть свои сервисы провайдеры и свои сервисы consumer. Но представьте себе, что это три разных человека которые разговоривают на разных языках и не понимают друг друга. И они решили отправлять друг другу какие-то сообщения. Это бессмысленно, так как они непонимают эти сообщения. Мы понимаем, что все поставщики ПО как правило разрабатывают свои форматы сообщений. В результате интеграции и взаимодействий сообщений от разных поставщиков практически исключенны. Поэтому плодилось большое число интеграторов – это компании разработчики ПО уровня middleware(промежуточное ПО). Они и являлись некими переводчиками, потому что крупные компании не считали для себя достойным придерживается формата своих конкурентов. Решением задачи удовлетворения универсальному требованию связанности является разработка некого стандартного формата сообщений, широкое распространение и принятие такого формата всеми поставщиками программных решений. И что же произошло? Крупные поставщики программных решений собрались и выработали некий стандарт и назвали его Web Service star. Мы видем что Web Service star – семейство спецификаций, определяющих универсальные форматы и структуру сообщений.

На этом слайде мы видим перечень спецификаций входящих в стандарт WS star. Те крупные поставщики, которые совместно выработали этот стандарт, они начали в своих сервис ориентированных приложениях, своих сервис ориентированных технологиях, придерживаться именно этого стандарта. С того времени, как этот стандарт был сформирован, сервисы от различных поставщиков научились понимать друг друга.

Давайте посмотрим теперь на такой стандарт. Был выработан, так называемый, SOAP (simple object access protocol), который представляет собой некий протокол в xml формате и мы видим, что основные теги которые в нем используются это Envelope (конверт), Header (заголовок), Body (тело). То-есть мы любое сообщение ассоциируем с конвертом. У нас есть конверт, Envelope, на него клеится наклейка, от кого и кому Header, а внутрь кладут письмо-сообщение, Body. Все как в жизни, как офисные сообщения. Вот такой простой формат сообщения, который получился. Такой формат понимают все сервисы всех поставщиков технологий и ПО.

Давайте посмотрим теперь, из чего же состоит сервис, или как мы их называем, сервис службы, и что это такое. На этом сладе мы видим блок, который, по сути, представляет собой некое представление хоста. Что это такое мы сейчас рассмотрим. Хост включает в себя некий core, сервисную логику, по сути это и есть бизнес логика сервиса. Но мы видим еще три важных компонента – Address, Binding, Contract, азбука WCF. Что такое адрес? Если я собираюсь приехать к Вам в гости домой, я должен знать, куда мне ехать. (Binding) Дальше важное условие, что язык общение будет русским, потому что если я приеду и буду общаться с Вами на китайском, и Вы его не знаете, то бессмысленная эта поездка и эта встреча. (Contract) Далее мы захотим определится с темой общения, зачем я к Вам приезжаю. Если я приеду к Вам домой что бы поговорить о WCF, а буду рассказывать анекдоты, то, скорее всего, вы скажите «Это не соответствует нашему соглашению (контракту)». Еще раз посмотрим основные компоненты сервиса провайдера, в данном случае. Это сама сервисная логика, здесь находятся методы, которые выполняют какую-то полезную деятельность. А Address, Binding и Contract представляют собой служебные блоки, которые отвечают за формирование и адреса, Binding отвечает за то, как мы будем общаться с сервисом, на каком языке будет происходить какое шифрование наших сообщений, вдруг мы хотим сделать так, что бы наши сообщения никто другой не смог прочитать. И Contract в жизни выражен обычным интерфейсом конструкции языка, а мы знает что интерфейсы содержат в себе наборы абстрактных методов, и получается что сервисную логику должен реализовывать этот интерфейс – Contract. И получается, что Core можно представить неким классом на языке С#, а Contract можно представить просто интерфейсом, который реализует этот класс.

Перейдем к следующему слайду и посмотрим, какие бывают разновидности сервисов, а точнее какие варианты физических частей архитектуры сервиса бывают. Обратите внимание на сервис провайдер. Это структура сервиса провайдера, то есть сервиса поставщика услуг. Слева структура сервиса consumer, потребителя услуг. Мы понимаем, что сервисы провайдеры размещаются на сервере, а сервисы consumer располагаются в клиентских частях определенных приложений. Но еще есть и гибридные сервисы, некие совместные сервисы. Он является и сервис провайдер и сервис consumer. Такого типа сервисы еще принято называть брокер. С брокером мы можем связаться, передать ему сообщение. Брокер обрабатывает это сообщение и выбирает нужны сервис провайдер, как бы переадресовуя это сообщение. Брокеры часто выступают даже в роли роутеров, то есть маршрутизаторов, либо балансировщиков нагрузки. Например, у нас недостаточно мощностей одного физического сервера и поэтому нам натипную логику нужно размещать на разных физических уровнях, то есть на нескольких разных серверах, так как запросов клиентов приходит очень много и мы не успеваем одним физическим сервером их обработать.

Посмотрим еще один важный момент. Что представляет собой так называемая конечная точка? Еще раз вспоминаем азбуку WCF – A (Address), B (Binding), C (Contract). Краткое определение: конечная точка – представляет собой совокупность адреса, контракта и привязки.

Сейчас мы и Вами посмотрим на пример который покажет, так сказать «Hello world!» в WCF или простейшее построение сервисов. Сейчас мы перейдем в Visual Studio и рассмотрим пример.

Давайте посмотрим структуру решения, из каких проектов состоит данное решение. У нас имеется два проекта – проект Client и проект Server. Проект Server описывает работу серверной части, то есть он описывает работу сервисов провайдеров. В Client у нас описывается работа сервисов consumer, то есть клиентские сервисы которые будут обращаться к сервисам провайдера за какими-то услугами. Обратите внимание, как в клиентской части так и в серверной части у нас имеется некий Contract.

Это и есть настоящий контракт, согласно которого будет происходить взаимодействие между сервис провайдером и сервис consumer. Предлагаю вернутся в презентацию и посмотреть графическое представление работы сервисов, а потом мы снова вернемся в этот проект.

На этом слайде мы видим графическое представление двух сервисов. Сервис провайдер, который находился в проекте Server и сервис consumer который находился в проекте Client. У нас имеется вот такое UML представление контракта, то есть интерфейса. Мы уже понимаем, что интерфейс и будет выступать полноценным контрактом для того что бы организовать работу между сервис провайдером и сервис consumer. Давайте посмотрим устройство сервис провайдера. В сервис провайдере у нас имеется некий класс, который называется Service и который реализует контракт IContract. Мы видим что интерфейс с именем IContract содержит в себе только один абстрактный метод Say, который принимает один строковой аргумент и ничего не возвращает. Получается что этот абстрактный метод мы должны будем реализовать в классе Service. Далее мы видим вот эту серую коробочку – это и есть хост. Хост представляет собой некий объект, который и представляет собой обьектно ориентированное представление полного сервис, потому что полный сервис включает в себя как хост, у нас имеется контракт, а контракт это обычный интерфейс, и у нас еще имеются специальные объекты Binding и Address. И далее у нас имеется класс Service. Понятно что будет построен экземпляр этого класса. И когда на сторону провайдера придет сообщение то хост проверит, соответствует ли оно контракту, соответствует ли оно Binding. И когда все соответствия будут удовлетворены то эта система хост создаст экземпляр класса Service, он сам его создаст динамически, и на этом экземпляре вызовет метод Say, из конверта он достанет аргумент и передаст этот аргумент методу Say. В данном случае мы видим, что возвращаемое значение отсутствует в этом методе, поэтому просто выполнится что-то на стороне сервера, а назад уйдет пустой конверт как бы подтвердив, что операция выполнилась. Это проблема с пустыми конверта у нас будет затрагиваться на курсе.

Давайте посмотрим теперь в сторону сервис consumer, то есть клиентскую сторону. Обратите внимание, клиент тоже работает по контракту. Это напоминает работу учебного центра – как у тренера, который является провайдером, поставщиком услуг, так и у клиента, студента, имеются одинаковые контракты. Но важно понимать, что студенческий контракт это требуемый контракт. На основании своего договора с учебный центром студент требует, что бы ему поставили знания. А со стороны учебного центра имеется контракт, на основании которого тренер должен предоставить знания. И поэтому контракт сервиса провайдера называется предоставляемым контрактом. Еще раз – контракт сервиса consumer называется требуемым контрактом, контракт сервиса провайдера называется предоставляемым контрактом. Конечно же тела этих контрактов должны совпадать. Давайте посмотрим, что имеется на стороне сервис consumer. У нас тут тоже имеется A, B, C – Address, Binding, Contract. Здесь у нас имеется блок клиентской логики. Что происходит в блоке клиентской логики? Здесь происходит какая-то посылка сообщений, мы сейчас это рассмотрим, на сторону сервис провайдера, сервис провайдер обрабатывает это сообщение и возвращает результат. Например, я, опять-таки, хочу узнать «Сколько будет 2+2?». Пишу сообщение, письмо, и отправляю провайдеру. Он сначала проверяет письмо, действительно ли он может складывать число, вдруг он умеет только умножать, на основании контракта видит, что у него есть метод добавления. Создается экземпляр класса, складываются два числа, формируется ответ, помещается в конверт и отправляется клиенту. Клиент открывает конверт и выводит 4 на экран пользователю, как пример. Далее, обратите внимание. Binding и Address. Дело в том, что как контракты, как байндинги, как адреса должны совпадать как со стороны сервис consumer, так и со стороны сервиса провайдера.

Давайте посмотрим, что представляет собой адрес. Адрес читается просто. Адрес http://127.0.0.0.1:4000/IContract читается так: используя транспорт http, например транспорт трамвай или автобус, идем на компьютер localhost, мы понимаем, что 127.0.0.1 совпадает с localhost, едим к такому-то дому, где в 4000 квартире, на порте 4000, нас ожидает человек с именем Иван (IContract), к примеру. Еще раз. Используя транспорт http идем на компьютер такой-то, где на порте 4000 нас ожидает некий сервис, который будет работать по контракту IContract, и он там сейчас находится и ожидает нас в гости, то есть ожидает нашего вызова.

Еще раз вернемся и видим, что здесь указали такой адрес. В данном случае мы используем localhost, используем 4000 порт и работаем по определенному контракту.

Интересно посмотреть на привязку, на Binding. Привязок у нас несколько, мы дальше будем их отдельно изучать, но сначала мы будем использовать самую простую привязку. Дело в том, что тип привязки должен обязательно совпадать с транспортной схемой, которую мы используем, то есть с http. Если мы в адресе используем протокол http, то соответственно мы и здесь должны взять binding с http. У нас здесь много разных байндингов, повторюсь, мы возьмем сейчас самый простой, без всяких шифровании. Будем слать просто текстовое сообщение, незашифрованное в самом простом виде. Вот правило – клиент должен использовать точно такие же параметры привязки, что и служба. Здесь создаются экземпляры класса BasicHttpBinding как на стороне сервиса consumer, так и на стороне сервиса провайдера. Повторюсь, что делает привязка – она проверяет моменты и шифрования, и много-много разных условий. Мы привязки будем отдельно детально рассматривать.

Теперь посмотрим, что представляет собой Contract. Мы уже видим, что Contract это простейший интерфейс, который должен реализовывать Service. Для того, что бы нам интерфейс сделать действительно настоящим WCF контрактом, нам требуется импортировать пространство имен ServiceModel в котором находятся важные атрибуты - атрибут ServiceContract и атрибут OperationContract. Так вот, для того что бы контракт стал контрактом мы его должны пометить атрибутом ServiceContract. В контракт может входить много различных методов, но не обязательно что бы все методы являлись часть контракта, может быть, есть какие-то внутренние методы сервиса, которые он не хочет предоставлять, так сказать, за свои границы. Так вот, те методы, к которым мы будем обращаться удаленно, со стороны клиентов, мы помечаем, иди декорируем, атрибутом OperationContract. То есть вот такой достаточно простой способ создания контрактов.

Теперь смотрим, для того что бы нам создать сам сервис нам нужно в нем реализовать интерфейс, который представляет собой контракт. И поэтому, обратите внимание, мы создаем обычный класс Service, он символизирует на диаграммах вот этот закругленный квадрат, реализуем в нем интерфейс IContract, обратите внимание, здесь у нас имеется реализация метода Say, который принимает один аргумент, ничего не возвращает и в теле метода выводится на экран строка, что сообщение получено, тело сообщение состоит из то-то то-то то-то. Достаточно просто.

Далее, давайте рассмотрим еще один важный момент – такое понятие как URI (Uniform Resource Identifier) – уникальный идентификатор ресурса. Представьте себе, что Вы пригласили меня в гости. Для того что бы мне приехать к Вам в гости, а вы живете, например, в коммунальной квартире, мне нужно знать, где же Вы располагаетесь, то есть Ваш адрес – номер Вашего дома, номер квартиры. Это описывается URL (Uniform Resource Locator) – уникальный указатель расположения ресурса. Когда я прихожу в Вашу большую коммунальную квартиру, звоню в дверь, выходит один из жильцов и говорит «Кто Вам нужен?», я говорю «Ну, я не знаю», он закроет дверь передо мной, если я не знаю. Поэтому я должен знать еще URN (Uniform Resource Name) – уникальный указатель имени ресурса. Я должен сказать, что хочу встретится с Андреем, или Мариной, с тем, кто живет по этому адресу. Почему? Потому, что по этому адресу может находится много сервисов и не понятно, к какому сервису я обращаюсь. И более того – у нескольких сервисов, которые висят на одном порте могут быть даже одноименные методы, поэтому мне нужно как-то указать имя контракта или имя сервиса, с которым я пришел пообщаться. Думаю, эта схема достаточно понятна в общем виде.

А мы продолжаем. Так вот, для того что бы нам создать так называемый хост, который в себе объединит конечную точку, конечная точка, мы помним, состоит из трех частей A, B, C (Address, Binding, Contract). Далее, собственно, сам экземпляр сервиса. Нам нужно выполнить следующие строки кода. Смотрим, мы создаем экземпляр класса Uri (Uniform Resource Identifier), мы его только что рассматривали, это новое представление, так как раньше был только URL и URN, теперь их объединили в собирательное понятие место размещения и имени ресурса. И мы видим, что мы создаем экземпляр класса Uri, называем его address и в качестве аргумента конструктора передаем полную строку адреса (http://127.0.0.0.1:4000/IContract). Далее мы создаем простейшую привязку, пока это обязательно. Почему простейшую? Потому, что она будет использовать транспортную схему http, никакого шифрования не будет, сообщение будет идти незашифрованная, текстовая информация. Далее, мы получаем экземпляр класса Type, который содержит в себе всю информацию об интерфейсе IContract. Обратите внимание, для того, что бы нам воспользоваться контрактом нам потребуется создать экземпляр класса Type, который содержит информацию об используемом контракте. И далее мы создаем экземпляр класса ServiceHost. Это и есть вот этот контейнер, который в себе объединит все составляющие сервиса, это и есть некая абстрактная представление физического сервиса. И мы его назовем host. Некий хозяин этого сервиса, который его обслуживает. Так вот, мы создаем экземпляр класса ServiceHost, в качестве аргумента конструктора передаем ссылку на экземпляр класса Type. Вы скажите, так здесь теперь понятно, когда на конечную точку придет сообщение, то что произойдет? Экземпляр класса ServiceHost воспользуется активатором CreateInstance, создаст экземпляр вот этого сервиса, вытащит с конверта аргументы, значения аргументов, и вызовет на этом сервисе метод Say, передаст ему аргументы, получит возвращаемое значение, упакует возвращаемое значение и отправит обратно клиенту по сети. Смотрите как просто, мы сами могли бы организовать вот такую логику. Далее, создали экземпляр класса ServiceHost, сконфигурировали его экземпляром класса Type, который содержит всю информацию о классе Service. Далее, на host вызываем метод AddServiceEndpoint и добавляем конечную точку, дело в том, что хост же должен иметь и свой адрес, и байндинг, и понимать по какому контракту он работает. Видим, мы добавляем A, B, C (Address, Binding, Contract). И, наконец, мы открываем его, то есть открываем двери в веб, в сеть. Все, мы говорим, мы слушаем. Мы слушаем, мы ждем, наши двери открыты и ждут от вас сообщений. Потому, что если мы не вызовем Open, хост будет создан, но мы пока никого не готовы принимать. В общем такая простая логика.

Давайте теперь посмотрим на клиентскую часть. Мы только что рассмотрели устройство сервис провайдера, теперь давайте посмотрим устройство сервис consumer. Понятно, что сервис consumer сам ничего делать не умеет, он может только спрашивать все у провайдера, а провайдер будет ему отвечать. Так вот, для того что бы связаться с провайдером существует вот такая абстракция, абстракция формирования канала. Я всегда говорю, вот представьте себе, что вы сервис consumer, студент, я – сервис провайдер. Вы хотите получить от меня информацию, но прежде Вам нужно со мной как-то наладить отношения. И поэтому, представьте себе, из Вашей головы выезжает зеленая труба и идет к моей голове, и мы начинаем переговариваться через эту трубу. То есть используя звуковые волны мы кодируем сообщение, оно летает по этой трубе, мои уши это воспринимают, голова обрабатывает и отвечает Вам. Та же самая абстракция используется и здесь. Сервис consumer делает вот такую трубу, то есть организует канал между собой, сервисом consumer, и требуемым ему сервис провайдером.

Давайте посмотрим, как же создается этот канал. Мы создаем тот же самой address, потому что мы должны обращаться по правильному адресу. Пользуемся той же самой привязкой. То есть, если я прихожу к Вам в гости, мы говорим с Вами на русском языке, ни от кого там не скрываемся, ничего не говорим секретными фразами, просто свободно общаемся и не шифруем наши сообщения. Далее мы создаем экземпляр объектно-ориентированного представления адреса конечной точки и передаем ему address, видите, конфигурируем EndPointAddress address. Важный момент, приступаем сначала к созданию фабрики каналов. Конечно же, прежде чем построить трубу, нам приходится построить саму фабрику, которая будет стоить эти зеленые трубы. Давайте посмотрим. Мы создаем экземпляр класса ChannelFactory и в качестве параметра типа передаем ему тип IContract. И далее, в аргументы конструктора передаем binding и передаем endpoint, мы видим, что endpoint в нашем случае содержит пока только address. Снова же смотрим – A, B, C (Address, Binding, Contract). Обратите внимания, фабрика созданная и теперь мы говорим фабрика, ты умеешь создавать каналы определенного типа, канал, который будет конектиться по определенному адресу, работать с определенным контрактом, работать на определенных языках шифрования или без шифрования. И получается, что здесь у нас создана фабрика, которая будет создавать такие зеленые трубы только к этому сервис провайдеру. Далее, на фабрике мы вызываем метод CreateChannel, говорим фабрика, сделай нам канал. Что делает фабрика? Фабрика создает некое объектно-ориентированное представление вот этого канал, но обратите внимание, что происходит, этот канал приводится к базовому интерфейсному типу IContract. Вы видите? Какая создается иллюзия, на стороне клиента будет создаваться иллюзия того, что я работаю непосредственно с этим сервис провайдером. Такое ощущение, что на моей машине, на моей клиентской машине имеется метод Say, я сюда передаю аргумент «Hello WCF!». То есть, вот эта техника как бы меня отстраняет от этих сервисных представлений, она заставляет меня думать, что как будто бы я работаю с сервисом у меня локально. Вот такая техника называется RPC (Remote procedure call) – удаленный вызов процедур. Вы скажите, а как же оно происходит? Очень просто, у нас имеется один очень важный патер, который называется прокси. И есть одна из разновидностей прокси, которая называется посол – представитель сервиса провайдера на стороне клиента. Этот посол, этот прокси, специальный объект, который также реализует интерфейс, который реализует сервис провайдер, и получается, что здесь у нас формируется тот же интерфейс взаимодействия, создается эта иллюзия настоящего сервиса. Только метод Say содержит хитрые и сложные механизмы, которые каким-то сложным образом связываются по сети с сервис провайдером, ожидают от него прихода сообщения и потом только Вам уже возвращают результаты этой работы. То есть не путайте, метод Say не содержит этой логики, метод Say содержит специальную техническую логику, благодаря которой мы связываемся с сервис провайдером, создавая, или формируя, иллюзию для клиента, ту иллюзию, которая и позволяет думать, как будто все происходит на клиентской стороне. Просто, достаточно просто.

Давайте снова же перейдем в Visual Studio и посмотрим на работу с сервисами, то есть посмотрим те же самые коды, попытаемся выполнить. Давайте сперва посмотрим на серверную сторону.

Заходим в интерфейс, обратите внимание, мы на первой строке импортируем пространство имен ServiceModel, на 8 строке мы создаем интерфейс с именем IContract, он, по сути, и будет являться контрактом нашего сервиса. Декорируем этот интерфейс атрибутом ServiceContract, что бы действительно сделать его настоящим WCF контрактом. Далее, на 11 строке, мы создаем абстрактный метод Say, который принимает один строковой аргумент и декорируем его атрибутом OperationContract. Достаточно просто. Давайте теперь зайдем в сам код сервиса.

На 7 строке мы создаем класс Service. Обратите внимание, не импортируем ничего, никаких специфических для WCF пространств имен. Просто создаем класс Service, и реализуем контракт. На 10 строке мы видим реализацию абстрактного метода Say из интерфейса IContract. И в теле этого метода просто выводим на экран строку, что бы оттенить момент получения и обработки пришедшего на сторону сервиса сообщения. То есть, мы оттеняем саму роботу сервиса.

Давайте теперь посмотрим на хостовую часть.

В теле метода main мы выводим в title слово SERVER, что бы понять, какой из окон консоли будет являться серверным, а какое будет клиентским. На 15 строке мы создаем экземпляр класса Uri и указываем address, создаем байндинг, то есть создаем привязку, привязка определяет правила обмена сообщениями между consumer и провайдером. И далее, на 21 строке мы создаем экземпляр класса Type, который будет содержать в себе информацию о контракте. На 25 строке мы создаем экземпляр класса ServiceHost, это и есть объектно-ориентированное представление вот этого контейнера, который будет содержать в себе и сервис, и конечную точку (Address, Binding, Contract), и конфигурируем ServiceHost экземпляром класса Type, видите, возвращаемое значение оператора typeof – это экземпляр класса Type, который будет содержать в себе всю информацию о сервисе, экземпляр которого мы захотим создать динамически, то есть в момент прихода сообщения. На 28 строке мы host конфигурируем нужной конечно точкой, передавая ему address, binding, contract, и открываем, говоря тем самым, что мы готовы к приему сообщений. Ну и тем самым мы оттеняем еще, вот эту готовность выводим пользователю сообщение, что мы готовы к приему сообщений. И после того, как сообщение принято, когда мы его уже обработали, после того как мы нажмем какую-то клавишу, то у нас хост закроется и больше сервис не будет способен принимать сообщения, если мы его закрыли. Достаточно просто. Вот она, собственно, серверная часть.

Давайте посмотрим на клиентскую часть. Клиент так же имеет интерфейс и этот интерфейс представляет собой клиентский контракт, и мы видим, что на 7 строке мы декорируем этот интерфейс специальным атрибутом ServiceContract, и на 11 строке мы создаем метод Say и декорируем его атрибутом OperationContract, то есть это клиентский требуемый контракт.

Давайте теперь перейдем собственно в сам Client. Мы смотрим, что на 12 строке оттеняем, что это консоль принадлежит клиенту, создаем address, binding, и создаем некое объектно-ориентированное представление адреса конечно точки, конфигурируем его адресам, и далее мы начинаем создавать саму фабрику каналов, потому что помните, нам потребуется создать вот этот канал, а его может создать только фабрика.

И вот, на 27 строке на созданной фабрике мы вызываем фабричный метод CreateChannel, который собственно и создает объектно-ориентированное представление канала, мы его еще можем называть либо прокси, либо даже проассоциировать с самим сервисом, потому что на клиентской стороне у нас должна создаваться иллюзия, что мы работаем непосредственно с сервисом. И уже теперь, на 30 строке, на канале, мы вызываем метод Say, которому в качестве аргумента передаем «Hello WCF!» и мы понимаем, что вот эта версия метода Say представляет собой некую обертку над сложным механизмом, который будет связываться с сервисом провайдером, будет отсылать ему сообщения и принимать от него сообщение, если конечно такая возможность имеется.

Давайте выполнимся теперь и посмотрим на результат роботы этой программы. Обратите внимание, вот сервер, он был готов к приему сообщений, и понятно, что клиент отправил сообщение, сервер это сообщение принял. Видите, вывел на экран сообщение «Сообщение получено, Тело содержит: Hello WCF! ». Мы видим, что отработал именно вот этот метод «Сообщение получено, Тело содержит…» Hello WCF, допустим.

И давайте рассмотрим еще один пример сервиса, который содержит метод возвращающий значение.

Давайте перейдем в интерфейс IContract. Мы видим, что на 8 строке мы создаем интерфейс IContract, помечаем его атрибутом ServiceContract. На 11 строке мы создаем абстрактный метод Say, который принимает один строковой аргумент и возвращает строковое значение, и помечаем этот метод атрибутом OperationContract.

Далее переходим в тело самого сервиса. На 7 строке мы создаем класс Service, который реализуем интерфейс IContract. На 10 строке мы реализуем метод Say из интерфейса IContract. Обратите внимание, этот метод Say принимает один аргумент и возвращает строковое значение. В теле метода мы оттеняем момент получения сообщения и отвечаем клиенту, говорим, что мы получили сообщение.

Далее зайдем в часть, которая описывает хост. Создаем address, binding, contract (получаем экземпляр класса Type, содержащий информацию о контракте), создаем сервис хост, добавляем конечную точку, запускаемся и ожидаем прихода сообщений.

Ну и далее, после того как сообщение пришло то мы закрываем хост.

Перейдем теперь в клиентский контракт.

Вы видите, что клиентский контракт, требуемый контракт, совпадает полностью с сервисным контрактом, многие скажут можно было бы сделать один контракт, dll библиотеку и просто подключать ее в клиентские проекты и в серверные. Да, так было бы правильно, но мы просто в этом учебном примере сдублировали этот интерфейс в разные проекты, но мы понимаем, что лучше его вынести отдельный проект, что бы избежать дублирование кода.

И теперь переходим к клиенту, так же создаем address, binding, создаем объектно-ориентированное представление адреса в контексте конечной точки, ниже мы создаем фабрику каналов, конфигурируем создаваемый объект конечной точкой, то есть адресом, binding и контрактом. Конечная точка, это все три составляющие, просто у нас идет создание EndpointAddress – адреса конечной точки. На 27 строке мы на фабрике вызываем метод CreateChannel, он возвращает нам ссылку на объектно-ориентированное представление канала, и на 30 строке используя технику RPC (Remote procedure call) мы на канале вызываем метод Say, передаем ему в качестве аргумента «Hello WCF!», этот Say связывается с сервисом, сервис обрабатывает его сообщение и возвращает ему «ОК», и соответственно Say примет это сообщение и запишет его в локальную строковую переменную response. На 32 выведет пользователю значение которое вернул сервис.

Давайте выполнимся и посмотрим.

Обратите внимание, сервер готов к приему сообщений, сообщение получено, тело состоит Hello WCF, клиент получил «OK», то, что мы и возвращали клиенту. Достаточно простой пример, который показывает, что сервис провайдер может вернуть в ответ на запрос клиента тоже какое-то значение, то есть результат роботы.

И мы переходим с Вами к краткому рассмотрению общей архитектуры WCF, что бы иметь некое общее представление именно архитектуры.

И на этом слайде мы с Вами видим некое общее представление всех архитектурных уровней WCF. Обратите внимание, вот эта часть обозначает клиентскую сторону, а вот эта часть – серверную сторону. Видите, здесь написано отправитель, получатель. Между отправителем и получателем циркулирует сообщения. Обратите внимание, на стороне отправителя имеется клиентская форма сервиса, на стороне получателя – серверная форма сервиса, то есть сервис провайдер. Здесь сервис consumer, здесь сервис провайдер. Обратите внимание, что вся эта диаграмма разделяется на две части. Дело в том, что возможно вы слышали про семиуровневую модель взаимодействия в сети, так вот WCF предоставляет упрощённую модель двухуровневую. Имеется уровень ServiceModel и уровень Channel. То есть некая сервисная модель, которая определяет именно бизнес логику, как бизнес логику consumer, так и бизнес логику провайдера. А здесь уже идет техническая часть. Обратите внимание, тут идут уровни протокольные, формирующие, транспортные, каналы различные, те что мы создавали с Вами каналы, вот эти сложности, потому что при передаче сообщений работает очень много различных протоколов, для того что бы те сообщения небыли утеряны. Но нас в данном случае пока не очень интересует этот уровень, мы уже будем рассматривать детальную работу таких уровней на более продвинутых курсах. Сейчас мы смотрим просто легко на архитектурные уровни WCF. И мы видим, что сверху этой планки находится клиентская логика, а здесь уже находится техническая логика, которая тоже можем нами настраиваться, но пока мы не будем этого делать. Мы видим, что когда клиент хочет передать сообщение, то на самом деле это сообщение передается через вот эту техническую прослойку, то есть через канальный уровень. Что сюда входит? Ну конечно же сюда входят определенные типы. Определенные типы, из которых состоит ServiceModel и определенные типы, из которых состоит уровень Channel. Вот сюда же входит фабрика каналов, например, которая стоит эти каналы. Более того, мы можем создавать свои каналы, если создавать свои каналы они сложно набираются из различных пайпов, из более мелких трубочек, которые позволяют более тонко налаживать взаимодействие между отправителем и получателем.

Давайте теперь рассмотри еще такую важную вещ, как категории функциональности, которые присутствуют в WCF. Мы видим, что вся основная функциональность разделяется на 10 категорий и мы поверхностно рассмотрим каждую из категорий, потому что более детально эти категории будут рассматриваться на отдельных уроках и других более продвинутых курсах WCF.

Первая категория это независимая модификация. Обратите внимание, у нас имеется сервер, имеются клиенты, которые подключены к этому серверу. И что у нас может происходить? У нас не выключая сервер можно как добавлять новые сервисы, вот видите, девушка презентует какой-то новый сервис, который позволит нам, к примеру, погоду. А вот здесь идут ремонтные работы на сервисе знакомств, там происходит какое-то обновление, что-то там изменили. То есть мы видим, что независимая модификация дает нам возможность изменять отдельные части системы, добавлять новые, не затрагивая при этом другие ее части. Если эти сервисы, этот сервис сейчас выключен, то вот эти прекрасно позволяют нам чатится и производить какие-то настройки. Если, к примеру, представить себе это как скайп.

Далее, асинхронный однонаправленный обмен сообщениями. Мы понимаем, что сервис consumer и сервис провайдер обмениваются друг с другом сообщениями и весь Интернет стоится по принципу, по правильному принципу «Запрос-Ответ». Прежде чем consumer, то есть пользователь, что-то получит, он должен сделать запрос на сервер. Даже если мы перейдем в представление того же скайпа, мы должны сначала обратится к сервису, сказать «Есть ли для меня сообщения?», он говорит «Да есть» и вернет вам. Я думаю все будут против, если сервер самостоятельно получит доступ к Вашей машине, то есть к модулям, которые расположены на Вашей машине. Дело в том, что компании производители, уважаемые компании производители как-то гарантировать, условно, что здесь нету брешей в безопасности, но мы все таки привыкли не доверять, потому что бывает, что ошибки и какие-то бреши в безопасности бывают и никому не хотелось бы что бы, например, злоумышленники получили доступ к их машинам. Вот поэтому чаще всего используется схема «Запрос-Ответ». Мы другие схемы тоже посмотрим.

Далее, платформенная консолидация – объединение возможностей многих предыдущих технологий в единую программную модель. Обратите внимание, у нас было очень много различных технологий. WSE это первая попытка реализации Web Service star спецификации. ASMX – это стандартные ASP сервисы. Remoting, тоже знакомая Вам технология для реализаций межпроцессных взаимодействий, межуровневых взаимодействий. COM+. MSMQ, мы знаем, что это некий аналог электронной почти не для людей, а для приложений, для программ. Так вот, у каждого были какие-то свои особенности, допустим, поддержка WS-* спецификаций была только у двух, взаимодействие с веб сервисами только у ASMX и COM+, чистая коммуникация .NET к .NET у Remoting, распределенные транзакции была в COM+ и MSMQ и гарантированная доставка сообщений, что те сообщения что идут на сторону сервера, они не будут утеряны. Так вот, WCF объединила в себе все вот такие возможности, которые имели какие-то предыдущие технологии до нее.

Далее, момент безопасности. Какие моменты безопасности у нас имеются? Аутентификация, авторизация, понятно, что аутентификация это когда мы логинимся на сайт, а авторизация это когда у нас в cookies у нас сохраняются, допустим, хеш коды которые потом отправляются сервер и потом происходит, допустим при обмене станиц, проверка, что вы действительно легальный пользователь. Далее, конфиденциальность, целостность. Конфиденциальность, что Ваши сообщения никто не прочитает. Целостность, что Ваше сообщение не было повреждено. Безопасность на уровне транспорта, что транспортные протоколы нормально доставили Ваше сообщение, без каких либо изменений. Безопасность на уровне сообщений, что сообщение не было изменено, допустим, пользователем. Те примеры, которые мы рассматривали, они не использовали, по сути, безопасности на уровне сообщений и мы гнали просто открытые сообщения.

Далее, надежность. WCF содержит механизмы, обеспечивающие три вида гарантии надежной доставки сообщений. Не более одного раза, то есть отправляете сообщение, а вот эти низкоуровневые системы, они пытаются как бы гарантировать, что сообщение будет доставлено, и может быть, что одно сообщение попытается прийти несколько раз. Хотя бы один раз, оно должно дойти. Либо вы отправляете серию своих пакетов и они должны по порядку дойти, допустим, что бы мы получили первое, второе, третье, четвертое, а не первое, четвертое, второе, третье.

Далее, поддержка транзакций. Мы видим, что транзакцией называется набор операций, и сбой одной операции приводит к сбою всего набора. Представьте, что consumer отправляет сообщение, брокер, видите, брокер это сообщение принимает, обрабатывает и отправляет кому-то другому. Например, вы перечисляете деньги. Допустим, отправляете в центра-банк, центра-банк это все обрабатывает, находит физический банк и отправляет уже эти деньги. Представьте, что здесь происходит какой-то сбой, в центра-банке, в брокере, и нам приходится делать откат этой транзакции. Так вот, вот эти процессы уже автоматизированы и на отдельных курсах мы с Вами будем их рассматривать. И вот, мы понимаем, что транзакция может находится в трех состояниях: это закрепленная транзакция, когда все хорошо прошло, отмененная транзакция, когда возникла ошибка и мы не можем выполнится, и сомнительная транзакция, когда вроде бы сообщение ушло, и где-то здесь потерялось, сюда не пришло, и здесь ответ тоже не пришел. В таком случае приходится уже вмешиваться живим людям, то есть администраторам и вручную либо править базы данных, либо исправлять все.

Следующее, сетевое взаимодействие (Interoperability). То есть, это способность системы менять программную или аппаратную платформу, не затрагивая других участников сценария распределенных вычислений. Вот представьте, что у нас какое-то время был, допустим, сервер Microsoft, работал на платформе .NET, пользовался SQL Server 2008. Вот сервисы как раз использовали такие технологии, такие платформы. И вы решили перейти на MySQL, что мало вероятно, конечно, на платформу mono, и, допустим, на Linux, например. Поэтому, мы можем взять, написать сервисы на других языках, например на Java, а наши клиентские Windows сервисы будут с ними связываться и так же хорошо работать, главное что бы так же правильно повторили логику сервисов провайдера. Ну, это те, кто боится платных платформ, что можно сначала попробовать на Microsoft серверах и, альтернативно, потом попробовать перейти на другие платформы. Конечно, это будет значительно дороже в разработке, потому что ни одна из альтернативных технологий, которые open source технологии, она не предоставляет таких богатых возможностей, какие предоставляет WCF.

Следующее, производительность. Мы понимаем, конечно, что производительность между Windows и Windows сервисами будет быстрее, чем между Windows и, например, Java сервисами. Почему? Потому, что здесь используется специальная кодировка, которая не работает с Java сервисами, почему? Потому, что сообщение в такой кодировки, например, Java не понимает, здесь приходится обмен либо в текстовом сообщении, либо если специальный формат, MTOM, ну и поэтому, конечно же, в таком случае производительность будет немножко ниже.

Расширяемость. Тоже важно. WCF позволяет создавать свои собственные: транспорт, вот у нас существует http, TCP, допустим, транспортные протоколы, вы можете создать свой транспортный протокол; свои каналы, допустим; свои привязки; свои кодировки; свои архитектурные парадигмы, то есть сказать да, я считаю что моя сервис-ориентированная архитектура, она завязана, допустим, на предметную область и я хочу взять и попробовать скрестить entity framework с WCF, где будут генерироваться какие-то хитрые сущности, смесь агентно-ориентированной архитектуры, которая будет взаимодействовать с тем-то тем-то, а это все не то, допустим, мне не хватает этих возможностей.

И так же возможность конфигурирования. Когда мы с Вами задавали конечные точки, мы их, так сказать, хард кодили – писали их в коде. Создавали конечную точку, указывали экземпляр адреса, привязки, получали экземпляр класса Type для контракта. Можно в программном коде этого не делать, а сделать это в конфигурационном файле. То есть, указать конечную точку, описание конечной точки, описать в конфигурационном файле, и тогда, если конечная точка, если администраторы, допустим, этого сервиса захотят поменять конечную точку, изменить адрес, например, или увеличить уровень безопасности сообщений, они могут уже самостоятельно прописывать нужные привязки, нужный адрес, и даже могут немножко открывать или закрывать уровни контракта, потому что мы понимаем, что у нас имеется такое понятие как узкого и широкого интерфейса, то есть когда один интерфейс наследуется от другого интерфейса, и соответственно вот эта игра через upcast и downcast может быть здесь так же применима.

И давайте посмотрим выводы, позволяет нам делать WCF. WCF позволяет проектировать, строить, отлаживать и сопровождать распределенные системы быстрее и более функционально, чем это было раньше. И мы познакомимся с большинством таких механизмов на протяжении серии курсов по WCF. WCF объединяет множество технологий: RPC, COM+, Remoting, ASMX, WSE и MSMQ. И так же, как мы понимаем WCF расширяема, но нужно задаться вопросом, нужно ли нам самостоятельно придумывать какие-то свои транспортные схемы, каналы, если и так очень много возможностей заложено в существующий набор типов WCF.

На этом наш урок закончен, спасибо за внимание, с Вами был Александр Шевчук, до новых встреч на ITVDN.

© 2017 ITVDN, все права защищены