Как я могу выполнить инициализацию в библиотеке служб WCF, которая не размещается самостоятельно? - PullRequest
1 голос
/ 20 апреля 2011

Я создал библиотеку службы WCF с простой службой тестирования 'hello world' и правильно настроенным файлом App.config, чтобы при запуске моего клиентского приложения служба WCF запускалась через встроенный хост Visual Studio. Служба в том виде, в каком она есть, работает нормально с внешней конфигурацией в моем клиенте.

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

Есть ли какой-нибудь способ, которым я могу перехватить некоторый код в библиотеке для вызова при запуске?

Ответы [ 2 ]

3 голосов
/ 21 апреля 2011

Я нашел еще один вопрос об использовании custom ServiceHostFactory для выполнения начальной загрузки , которая настраивается с помощью файла *.svc. Файлы *.svc являются частью приложения-службы WCF и не могут напрямую использоваться службой WCF Библиотека . Я хочу использовать библиотеку сервисов для некоторой гибкости с моей реализацией сервисов и возможным производственным хостингом, но использование сервисного приложения WCF позволило бы выполнить работу способом, подходящим для разработки (и, вероятно, было бы достаточно просто отбросить в IIS для производственного хостинга с альтернативным набором конфигурации). Поэтому я решил, что мне просто нужно создать приложение службы WCF, которое выступает в качестве хоста для служб в библиотеке служб и выполняет требуемую инициализацию.

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

В файле Web.Config приложения-службы в разделе <configSections>..</configSections> (который должен быть первым узлом после тега <configuration>) я добавил раздел <system.serviceModel> для библиотеки служб (это может быть извлечено из файла App.config в служебной библиотеке и отредактировано в соответствии с требованиями).

Например:

<system.serviceModel>
  <services>
    <service behaviorConfiguration="MyServiceBehavior" name="BelfryImages.QueryService.Implementation.HelloWorld">
      <endpoint address="HelloWorld" binding="wsHttpBinding" name="HelloWorld" contract="BelfryImages.QueryService.Contracts.IHelloWorld" />
    </service>
  </services>

  <behaviors>
    <serviceBehaviors>
      <behavior name="MyServiceBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>

  <bindings>
  </bindings>
</system.serviceModel>

Обратите внимание, что BelfryImages.QueryService.Implementation.HelloWorld является FQN реализации службы (класс реализации) контракта на обслуживание (интерфейса) BelfryImages.QueryService.Contracts.IHelloWorld. У меня фактически есть это в двух отдельных сборках; BelfryImages.QueryService.Contracts.dll - Сервисная библиотека WCF.

Я добавил новый пустой файл .svc в приложение-службу, названный в соответствии с конечной точкой, например HelloWorld.svc. Обычно добавление службы WCF к приложению службы WCF приводит к созданию файла .svc и файла кодовой привязки .cs, в котором содержится реализация службы. Я вручную добавил только файл .svc без кода и указал его на реализацию библиотеки служб:

<%@ ServiceHost Language="C#" Debug="true" Service="BelfryImages.QueryService.Implementation.HelloWorld" %>

В нынешнем виде это можно было использовать в качестве замены для служебной библиотеки, размещенной на VS, после первого изменения URL-адреса службы клиента с http://localhost:XXXXX/QueryService/HelloWorld на http://localhost:XXXXX/HelloWorld.svc/HelloWorld.

Затем я создал ServiceHostFactory для выполнения инициализации службы. Я нашел статью MSDN ( Хостинг и использование служб WCF ), в которой объясняется, как это сделать (листинги 5-6 и 5-7) - для своих целей я просто добавил более простое, общего назначения CustomHostFactory класс:

public class CustomHostFactory
    : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        // perform initialisation:
        ...

        var serviceHost = base.CreateServiceHost(serviceType, baseAddresses);
        return serviceHost;
    }
}

Затем он привязывается к службе в файле .svc путем добавления атрибута Factory:

<%@ ServiceHost Language="C#" Debug="true" Service="BelfryImages.QueryService.Implementation.HelloWorld" Factory="BelfryImages.WcfService.CustomHostFactory" %>

Инициализация в верхней части переопределения CreateServiceHost() выполняется до того, как служба создается как обычно. Кажется, что это происходит только один раз для каждой службы, а не один раз для каждого вызова службы, но для нескольких служб будут накладные расходы. Это, вероятно, можно сделать одноразовым, используя статический флаг или подобное. На данный момент все работает нормально.

1 голос
/ 20 апреля 2011

Будет ли работать иметь код инициализации в статическом конструкторе класса, который реализует ваш сервис?

public class WCFService : IWCFService
{
    static WCFService()
    {
        // do initializing here
    }

}

Этот код будет выполняться при первом вызове службы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...