Введение
Этот документ дает высокоуровневый обзор архитектуры Windows Communication Foundation (WCF). Он призван описать ключевые концепции, заложенные в WCF, и то, как они связаны друг с другом. Документ содержит примеры кода, которые иллюстрируют основные концепции, но не являются руководством по кодированию в WCF.
Документ состоит из двух основных секций:
· Основы WCF: описывает ключевые концепции WCF, термины и компоненты архитектуры. · Примеры кода: Представляют несколько кратких примеров, которые иллюстрируют и демонстрируют применение концепций изложенных в предыдущем разделе.
Клиент – это программа, которая обменивается сообщениями с одной или несколькими конечными точками. Клиент также может публиковать конечную точку для приема сообщений от сервиса для реализации шаблона дуплексного обмена сообщениями.
Следующие секции раскрывают эти понятия более детально.
Конечная точка сервиса имеет адрес (Address), привязку (Binding), и контракт (Contract).
Адрес конечной точки – это сетевой адрес ее расположения. Класс EndpointAddress представляет адрес конечной точки.
Привязка конечной точки определяет, как она сообщается с внешним миром, включая такие параметры, как транспортный протокол (напр., TCP, HTTP), кодировка (напр., text, binary), и параметры безопасности (напр., SSL, SOAP message security). Класс Binding представляет привязку WCF.
Контракт конечной точки определяет, что составляет предмет общения конечной точки, и по существу представляет собой коллекцию сообщений собранных в операции в соответствии с базовыми шаблонами обмена сообщениями (basic Message Exchange Patterns - MEPs) такими, как симплекс, дуплекс, запрос/ответ. Класс ContractDescription представляет WCF контракт.
Класс ServiceEndpoint представляет конечную точку и содержит классы EndpointAddress, Binding, и ContractDescription представляющие адрес, привязку и контракт соответствующей конечной точки. (см. Рис. 1).
EndpointAddress содержит URI, удостоверение (Identity), и коллекцию необязательных заголовков (headers), как показано на рисунке 2.
Удостоверение конечной точки обычно привязано к ее URI, однако в некоторых сценариях использования удостоверение можно задать явно, вне зависимости от URI, используя свойство адреса Identity.
Опциональные заголовки представляют дополнительную адресную информацию помимо URI конечной точки. Например заголовки адреса используются определения конкретной конечной точки из нескольких, которые используют одинаковый URI.
Рис. 2. Класс EndpointAddress содержит URI, Identity и коллекцию AddressHeaders.
Привязки
Привязка имеет имя, пространство имен, а также коллекцию компонуемых элементов привязки (BindingElement) (рис. 3). Имя и пространство имен привязки уникально идентифицируют ее а пределах сервиса. Каждый элемент привязки описывает как конечная точка общается с вешним миром. Рис. 3. Класс Binding и его члены.
Например, на рисунке 4 показана коллекция из трех элементов привязки. Наличие каждого из этих элементов привязки описывает конкретный аспект взаимодействия в конечной точкой. TcpTransportBindingElement показывает что конечная точка будет взаимодействовать с внешним миром, используя TCP в качестве транспортного протокола. ReliableSessionBindingElement говорит о том, что конечная точка использует гарантированную доставку сообщений. SecurityBindingElement указывает на то, что конечная точка использует механизм защиты на уровне сообщений SOAP. Каждый элемент привязки обычно имеет свойства которые более конкретно описывают как взаимодействует конечная точка с внешним миром. Например, ReliableSessionBindingElement имеет свойство Assurances, которое определяет уровень требований по гарантированной доставке каждого сообщения, такой как негарантированная доставка (none), не менее одного раза, не более одного раза, только один раз.
Порядок следования элементов привязки является значимым, потому что коллекция элементов используется для построения коммуникационного стека в соответствии с порядком элементов. Элемент привязки, последним добавленный в коллекцию, соответствует нижнему компоненту коммуникационного стека, а тот элемент который был добавлен первым, соответствует верхнему компоненту стека. Входящие сообщения проходят коммуникационный стек от нижнего компонента к верхнему, а исходящие наоборот, от верхнего к нижнему. Таким образом порядок элементов привязки в коллекции оказывает непосредственное влияние на то, как порядок в котором компоненты коммуникационного стека обрабатывают сообщения. WCF предоставляет набор предопределенных привязок, которые могут быть использованы для в большинства сценариев взаимодействия без определения специфических пользовательских привязок.
Контракты
Контракт WCF это коллекция операций, которые определяют, как конечная точка общается с внешним миром. Каждая операция представляет собой единицу обмена сообщениями, например, односторонний обмен сообщениями или обмен по схеме запрос/ответ.
Класс ContractDescription используется для описания контракта WCF и его операций. Внутри ContractDescription, каждая операция представлена соотвтествующим экземпляром класса OperationDescription, который описывает различные аспекты операции, такие как будет ли операция однонаправленной или по схеме запрос/ответ. Каждый OperationDescription содержит коллекцию MessageDescriptions, кторая описывает сообщения данной операции.
ContractDescription обычно создается на основе типа или интерфейса который определяет контракт используя программную модель WCF. Этот тип описывается с помощью атрибута ServiceContractAttribute, а его методы, которые соответствуют операциям конечной точки помечаются атрибутом OperationContractAttribute. Вы также можете создать ContractDescription в ручную без использования CLR типа, подписанного соответствующими атрибутами.
Дуплексный (duplex) контракт определяет два логических набора операций: набор операций, которые сервис предоставляет клиенту для вызова, и набор операций, которые клиент предоставляет для вызова сервису. Программная модель дуплексного контракта определяет каждый набор операций в виде отдельного класса (или интерфейса), при этом класс определяющий контракт сервиса помечается атрибутом ServiceContractAttribute, кторый в свою очередь ссылается на класс, определяющий контракт клиентских (callback) операций. Поэтому ContractDescription содержит ссылки на оба типа реализующие клиентский и сервисный наборы операций, группируя таким образом их в один дуплексный контракт.
Подобно привязкам, каждый контракт имеет имя и пространство имен, которые уникально идентифицируют его в метаданных сервиса.
Каждый контракт также имеет коллекцию ContractBehaviors, содержащую модули, котрые расширяют или модифицируют поведение контракта. Следующая секция описывает поведения более детально.Рис. 5. Класс ContractDescription описывает контракт WCF
Поведения это типы, которые расширяют или модифицируют функциональность сервиса или клиента. Например ServiceMetadataBehavior управляет поведением сервиса при публикации метаданных. Подобным образом поведение безопасности управляет имперсонацией и авторизацией, поведение транзакций управляет участием в транзакциях и их авто-завершением.
Поведения также принимают участие в создании канала и поэтому могут модифицировать его на основе пользовательских настроек, а также управлять другими аспектами сервиса или канала.
Поведение сервиса это тип, который реализует интерфейс IServiceBehavior и применяется к сервису. Поведение канала это тип который реализует IChannelBehavior и применяется к клиентским каналам.
Описатели сервисов и каналов
Класс ServiceDescription представляет собой хранимую в оперативной памяти структуру, которая описывает сервис WCF включая его конечные точки, поведения, применяемые к этому сервису, а также тип (класс) который реализует сервис (см. Рис. 6). ServiceDescription используется для создания метаданных, конфигурации и каналов.
Вы можете создавать описатели сервисов в ручную. Также вы можете создать его из типов, помеченных определенными атрибутами WCF, и это является наиболее предпочтительным сценарием. Код для этого типа может быть написан в ручную или сгенерирован из WSDL с использованием инструмента svcutil.exe.
Несмотря на то, что объекты описателей сервисов могут быть созданы и наполнены явным образом, часто они создаются за кулисами как часть процесса исполнения сервиса.
Точно также на клиентской стороне ChannelDescription описывает клиентский канал WCF для конкретной конечной точки (рис. 7). Класс ChannelDescription содержит коллекцию IСhannelBehavior, представляющую поведения, применяемые к этому каналу. От также содержит ServiceEndpoint, котрый описывает конечную точку с которой этот канал будет взаимодействовать.
Заметьте, что в отличие от ServiceDescription, ChannelDescription описывает только одну конечную точку, с которой канал будет взаимодействовать.
Рис. 7. Объектная модель ChannelDescription
Среда исполнения WCF
Среда исполнения WCF это набор объектов, отвечающих за прием и передачу сообщений. Например, такие вещи, как форматирование сообщений, обеспечение безопасности, передача и прием сообщений с использованием различных транспортных протоколов, а также диспетчеризация принимаемых сообщений между соответствующими операциям, все это обеспечивается средой исполнения WCF.
Сообщение
Сообщение WCF это единица обмена данных между клиентом и конечной точкой сервиса. По своей сути Message WCF являeтся представлением сообщений SOAP InfoSet. Отметим что сообщения не имеют жесткой привязки к формату текстового представления XML. Вместо этого, в зависимости от используемого механизма кодировки, сообщение может быть сериализовано в двоичный формат WCF, текстовый XML, или любой другой формат специальный формат.
Каналы
Каналы представляют собой базовую абстракцию для механизма передачи сообщений в и приема сообщений из конечной точки. Вообще говоря, существует две категории каналов: первая, это транспортные каналы, которые принимают или передают бинарные потоки, используя для этого транспортные протоколы, такие как TCP, UDP или MSMQ. Вторая категория, это каналы протокола, которые реализуют базирующиеся на SOAP протоколы обработки и модификации сообщений. Например, канал безопасности (security channel) обеспечивает обработку специальных заголовков SOAP сообщений, а также может модифицировать тело сообщения, шифруя его. Каналы компонуются таким образом, чтобы обеспечить последовательную обработку сообщения несколькими каналами.
EndpointListener
Класс EndpointListener реализует конечную точку (ServiceEndpoint) во время исполнения. Свойства EndpointAddress, Contract, и Binding класса ServiceEndpoint (определяющие где, что и каким образом), соотносятся с такими свойствами EndpointListener-а, как адрес, диспетчер и фильтры сообщений и стек каналов соответственно. EndpointListener содержит стек каналов, который отвечает за отправку и прием сообщений.
ServiceHost и ChannelFactory
Среда исполнения WCF обычно создается при вызове метода ServiceHost.Open. ServiceHost (рис. 8) управляет созданием описателя сервиса (ServiceDescription) на основе типа реализующего сервис и заполнением коллекции конечных точек (ServiceEndpoint) определенных в коде и/или в конфигурационном файле. Затем ServiceHost использует полученный таким образом ServiceDescription при создании стека каналов в каждом из EndpointListener, которые создаются для каждой конечной точки (ServiceEndpoint) описателя сервиса (ServiceDescription).
Рис. 8. Объектная модель ServiceHost
Подобным образом на клиентской стороне, клиентская среда исполнения создается посредством класса ChannelFactory, который является клиентским эквивалентом класса ServiceHost.
ChannelFactory управляет созданием описателя канала (ChannelDescription), используя для этого тип, реализующий клиентский контракт, привязку и адрес конечной точки. Созданный описатель канала (ChannelDescription) используется для построения стека каналов.
В отличие от среды исполнения сервиса, клиентская среда исполнения не содержит EndpointListener-ов, потому что клиент всегда сам инициирует соединение с сервисом и ему не нужно «прослушивать» входящие соединения.
Примеры кода
Эта секция представляет примеры кода, которые иллюстрируют как создаются сервисы и клиенты. Данные примеры предназначены для иллюстрации основных концепций, а не для обучения приемам программирования в WCF.
Определение и реализация контракта
Как упоминалось выше, простейшим способом определить контракт является создание интерфейса или класса, помеченного атрибутом ServiceContractAttribute, позволяющее системе легко создать на его основе описатель контракта (ContractDescription).
Когда мы используем класс или интерфейс для определения контракта, каждый метод, который является членом контракта должен быть помечен атрибутом OperationContractAttribute. Например:
using System.ServiceModel;Реализация контракта в данном случае сводится к созданию класса, реализующего IMath. Этот класс становится классом сервиса WCF. Например:
//конракт WCF определен с использованием интерфейса
[ServiceContract]
public interface IMath
{
[OperationContract]
int Add(int x, int y);
}
//этот класс сервиса реализует интерфейс
public class MathService : IMath
{
public int Add(int x, int y)
{ return x + y; }
}
Определение конечных точек и запуск сервиса
Конечные точки могут быть определены в коде или в конфигурационном файле. В примере, приведенном ниже, метод DefineEndpointImperatively демонстрирует простейший способ определения конечной точки в коде и запуска сервиса.
Метод DefineEndpointInConfig, демонстрирует определение аналогичной конечной точки при помощи конфигурационного файла (пример конфигурационного файла приведен ниже)
public class WCFServiceApp
{
public void
DefineEndpointImperatively()
{
//создаем хост для сервиса MathService
ServiceHost sh = new
ServiceHost(typeof(MathService));
//используем метод AddEndpoint для
//создания конечной точки
ServiceEndpoint и включения ее
//в описание
сервиса ServiceDescription
sh.AddServiceEndpoint(
typeof(IMath), //тип,
реализующий контракт
new WSHttpBinding(), //одна из стандартных привязок
"http://localhost/MathService/Ep1"); //адрес конечной точки
//создаем и открываем среду исполнения сервиса
sh.Open();
}
public void DefineEndpointInConfig()
{
создаем хост для сервиса
MathService
ServiceHost sh = new ServiceHost (typeof(MathService));
//создаем и открываем среду исполнения сервиса
sh.Open();
}
}
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.servicemodel>
<services>
<service type="MathService">
<endpoint contract="IMath" binding="wsHttpBinding" address="http://localhost/MathService/Ep1">
</service>
</services>
</system.servicemodel>
</configuration>
Отправка сообщений конечной точке сервиса
Код, приведенный ниже, демонстрирует два способа отправки сообщения кончной точке сервиса IMath. Метод SendMessageToEndpoint скрывает создание канала, которое происходит за кулисами вызова, а метод SendMessageToEndpointUsingChannel демонстрирует явное создание канала.
Первый пример (SendMessageToEndpoint) использует утилиту svcutil.exe и метаданные сервиса для генерации контракта (IMath в этом примере), прокси класса (MathProxy), который реализует контракт, и связанного с ним конфигурационного файла (не показан в примере). В этом случае контракт, определяемый интерфейсом IMath определяет что (т.е. опрации, которые могут быть выполнены), в то время как сгенерированный конфигурационный файл содержит привязку (каким образом) и адрес (где).
Использовать этот прокси класс, означает создать его экземпляр и вызвать метод Add. За кулисами прокси класс создаст канал и использует его для связи с конечной точкой сервиса.
Во втором примере, в методе SendMessageToEndpointsUsingChannel демонстрируется создание связи с конечной точкой сервиса путем прямого использования ChannelFactory. В этом примере, вместо использования прокси класса и конфигурационного файла, канал создается явно методом ChannelFactory
using System.ServiceModel;Определение специального поведения
//этот контракт сгенерирован утилитой svcutil.exe
//из метаданных сервиса
public interface IMath
{
[OperationContract]
public int Add(int x, int y)
{ return x + y; }
}
//этот класс сгенерирован утилитой svcutil.exe
//из
метаданных сервиса
//сгенерированный config не показан здесь
public
class MathProxy : IMath
{
...
}
public class WCFClientApp
{
public void SendMessageToEndpoint()
{
//используем прокси
класс, который бвл
//создан утилитой svcutil.exe на основе метаданных
сервиса
MathProxy proxy = new MathProxy();
int result =
proxy.Add(35, 7);
}
public void SendMessageToEndpointUsingChannel()
{
//используем ChannelFactory чтобы создать канал
//вы должны
указать адрес, привязку и
//тип, реализующий контракт (IMath)
ChannelFactoryfactory=new ChannelFactory (
new
WSHttpBinding(),
new EndpointAddress("http://localhost/MathService/Ep1"));
IMath channel=factory.CreateChannel();
int result=channel.Add(35,7);
factory.Close();
}
}
Определение специального поведения заключается в реализации интерфейса IServiceBehavior (или IChannelBehavior в случае клиентского поведения). Код, приведенный ниже, демонстрирует пример поведения, которе реализует интерфейс IServiceBehavior. В реализации метода IServiceBehavior.ApplyBehavior код просматривает описатель сервиса ServiceDescription и выводит адрес, привязку и контракт для каждой конечной точки сервиса, а также имена всех поведений в ServiceDescription.
Это конкретное поведение использует также атрибут (унаследованный от System.Attribute) для того, чтобы сделать возможным декларативный стиль своего применения, как будет показано ниже. Однако, в целом, поведения не требуют использования атрибутов.
[AttributeUsageAttribute(Применение специального поведения
AttributeTargets.Class,
AllowMultiple=false,
Inherited=false)]
public class
InspectorBehavior : System.Attribute,
System.ServiceModel.IServiceBehavior
{
public void ApplyBehavior(
ServiceDescription description,
Collectionbehaviors)
{
Console.WriteLine("-------- Конечные точки ---------");
foreach
(ServiceEndpoint endpoint in description.Endpoints)
{
Console.WriteLine("--> Конечная точка");
Console.WriteLine("Endpoint
Address: {0}",
endpoint.Address);
Console.WriteLine("Endpoint Binding:
{0}",
endpoint.Binding.GetType().Name);
Console.WriteLine("Endpoint
Contract: {0}",
endpoint.Contract.ContractType.Name);
Console.WriteLine();
}
Console.WriteLine("-------- Поведения сервиса
--------");
foreach (IServiceBehavior behavior in description.Behaviors)
{
Console.WriteLine("--> Поведение");
Console.WriteLine("Behavior: {0}", behavior.GetType().Name);
Console.WriteLine();
}
}
}
Все поведения могут быть применены имплементативно, путем добавления экземпляра поведения в ServiceDescription (или в ChannelDescription на клиентской стороне). Например,для имплементативного применения поведения InspectorBehavior используем следующий код:
ServiceHost sh = new
ServiceHost(typeof(MathService));
sh.AddServiceEndpoint(
typeof(IMath),
new WSHttpBinding(),
"http://localhost/MathService/Ep1");
//Добавляем поведение явно
InspectorBehavior behavior = new
InspectorBehavior();
sh.Description.Behaviors.Add(behavior);
sh.Open();
Дополнительно, поведения, которые унаследованы от System.Attribute могут быть применены к сервису декларативно. Например, поскольку InspectorBehavior унаследован от System.Attribute, он может быть применен декларативно, как показано здесь:
[InspectorBehavior]
public class MathService :
IMath
{
public int Add(int x, int y)
{ return x + y; }
}
Заключительный обзор
Сервис WCF публикует коллекцию конечных точек, где каждая конечная точка является порталом для взаимодействия с внешним миром. Каждая конечная точка имеет адрес, привязку, и контракт (анг. аббревиатура - ABC). Адрес определяет где расположена конечная точка, привязка определяет каким образом можно связаться с конечной точкой, и контракт определяет что представляет из себя конечная точка.
Для каждого сервиса существует описатель сервиса (ServiceDescription) который содержит коллекцию описателей конечных точек публикуемых этим сервисом. На основании этого описателя ServiceHost создает среду исполнения сервиса, которая содержит EndpointListener для каждой конечной точки сервиса. Адресу, привязке и контракту конечной точки, соответствуют адрес, диспетчер и фильтр сообщений и стек каналов EndpointListener-а соответственно.
Аналогичным образом, на клиенте, описатель канала содержит одну конечную точку, с которой связывается клиент. Используя описатель канала, ChannelFactory создает стек каналов который может общаться с конечной точкой сервиса.
3 комментария:
Перевод отвратительный.
нормальный перевод.
Перевод "мама не горюй"! На английском понятнее на много
Отправить комментарий