вторник, 1 апреля 2008 г.

Loosely-coupled WCF service

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

Замечу сразу, что реализация основана на статьях Roman Kiss'а на codeproject, в которых он при помощи WCF сервисов реализует различные WS-* протоколы. Вот эти статьи:
Идея подхода следующая - отделить код сервиса от непосредственной работы с ресурсами при помощи адаптера сервиса (ServiceAdaptor). Реализация основана на модели расширения WCF, которая отлично описана в статье Aaron Skonnard'а Extending WCF with custom behaviors (к сожалению статья на русском - не знаю как заставить MSDN выдавать статьи на том языке, который мне нужен, а не на том который у меня на компе).

Основа решения состоит из следующих элементов:
  • базовый класс сервиса, для доступа к адаптеру;
  • поведение, применяемое к сервису, для создания адаптера;
  • конфигурационной элемент, для настройки поведения в конфиге;

Далее, для каждой конкретной реализации необходимы:

  • интерфейс адаптера, который будет выполнять необходимую сервису работу;
  • класс, реализующий интерфейс адаптера;
  • класс, реализующий контракт сервиса, унаследованный от базового класса с адаптером.

Вот и все теперь по частям:

ServiceAdapterBase

Базовый класс, инкапсулирующий логику получения объекта адаптера из инфрастуктуры WCF.

Здесь мое главное усовершенствование. Адаптер впервые создается при первом обращении к нему из методов контракта. Такое решение позволяет добиться следующих преимуществ:

  • сервис сам управляет временем жизни адаптера (экземпляр адаптера существует в каждом экземпляре сервиса, соответственно их времена жизни равны);
  • при установке ServiceBehavior.InstanceContextMode = Single становится невозможным создать адаптер, при поведении применяемом в конфигурационном файлеб ниоткуда кроме текущей операции, т.к. при создании объекта singlton-сервиса инфраструктура wcf еще не инициаллизирована и поведение применяемое в конфиге позволяет расширить wcf только на уровне сервиса или endpoint.


AdapterAttribute - service behavior

Класс, реализующий интерфейс IServiceBehavior, с помощью которого наше поведение подключается к инфраструктуре WCF. Ничего не делает, просто предоставляет данные, необходимые для создания сервиса. Т.к. наше поведение реализовано в классе атрибута, то оно может применяться и декларативно - в коде.



ServiceAdapterBehaviorElement

Класс, необходимый для подключения поведения в файле настроек.



Конкретная реализация

ITestAdapter, TestAdapter


IService, Service



Обратите внимание на параметр типа ServiceAdapter в ServiceAdapterBase - здесь вы можете жестко в коде прошить класс адаптера (удобно для разработчика - можно быстро менять реализацию сервиса). Для того чтобы дать понять классу ServiceAdapterBase, что конкретный тип адаптера будет задан в конфиге ему подставляется затычка - ConfigurableAdapter (пустой класс даже картинку не буду вешать).


И теперь последняя деталь - файл конфигурации:



P.S. С выходом .Net framework 3.5 та же функциональность слегкостью может быть достигнута при помощи модели WorkflowServices и loose-xoml. Почитайте у Roman'а http://www.codeproject.com/KB/WF/VirtualServiceForESB.aspx


Удачи!

Комментариев нет: