我发现另一个关于使用custom ServiceHostFactory to perform bootstrapping 的问题,它是通过*.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是服务契约(接口)BelfryImages.QueryService.Contracts.IHelloWorld的服务实现(实现类)的FQN。实际上,我将它们放在两个单独的程序集中; BelfryImages.QueryService.Contracts.dll 是 WCF 服务库。
我向服务应用程序添加了一个新的空白.svc 文件,命名为与端点匹配,例如HelloWorld.svc。通常,将 WCF 服务添加到 WCF 服务应用程序会生成一个 .svc 文件和一个 .cs 代码隐藏文件,其中包含服务的实现。我手动添加了 .svc 文件,没有代码隐藏,并将其指向服务库实现:
<%@ ServiceHost Language="C#" Debug="true" Service="BelfryImages.QueryService.Implementation.HelloWorld" %>
在首先将客户端的服务 URL 从 http://localhost:XXXXX/QueryService/HelloWorld 更改为 http://localhost:XXXXX/HelloWorld.svc/HelloWorld 之后,它可以用作 VS 托管服务库的直接替代品。
然后我创建了ServiceHostFactory 来执行服务的初始化。我发现了一篇 MSDN 文章 (Hosting and Consuming WCF Services) 解释了 how to do this(清单 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;
}
}
然后通过添加Factory 属性将其绑定到.svc 文件中的服务:
<%@ ServiceHost Language="C#" Debug="true" Service="BelfryImages.QueryService.Implementation.HelloWorld" Factory="BelfryImages.WcfService.CustomHostFactory" %>
CreateServiceHost() 覆盖顶部的初始化在照常创建服务之前执行。这似乎每个服务只发生一次,而不是每次调用服务一次,但是多个服务会有开销。通过使用静态标志或类似的东西,这可能是一次性的。目前它似乎工作正常。