使用 ServiceHostFactory 扩展托管

Windows Communication Foundation(WCF)中托管服务的标准 ServiceHost API 是 WCF 体系结构中的扩展点。 在打开服务之前,用户可以从 ServiceHost 派生各自的宿主类,通常是重写 OnOpening() 以使用 ServiceDescription 来以强制方式添加默认终结点或修改行为。

在自承载环境中,无需创建自定义 ServiceHost ,因为你编写了实例化主机的代码,然后在实例化主机后对其进行调用 Open() 。 在这两个步骤之间,你可以做任何你想做的事情。 例如,可以添加新的 IServiceBehavior

public static void Main()  
{  
   ServiceHost host = new ServiceHost( typeof( MyService ) );  
   host.Description.Add( new MyServiceBehavior() );  
   host.Open();  
  
   ...  
}  

此方法不可重用。 作说明的代码将编码到主机程序(在本例中为 Main()函数中,因此很难在其他上下文中重复使用该逻辑。 还有其他不需要命令性代码的方法来添加IServiceBehavior。 可以从ServiceBehaviorAttribute派生一个属性并将其应用于服务实现类型,也可以使自定义行为可配置并动态地通过配置进行组合。

但是,该示例的细微变化也可用于解决此问题。 一个办法是将添加 ServiceBehavior 的代码从 Main() 中移动到 OnOpening 的自定义派生的 ServiceHost 方法中:

public class DerivedHost : ServiceHost  
{  
   public DerivedHost( Type t, params Uri baseAddresses ) :  
      base( t, baseAddresses ) {}  
  
   public override void OnOpening()  
   {  
  this.Description.Add( new MyServiceBehavior() );  
   }  
}  

然后,您可以在Main()的内部使用以下内容:

public static void Main()  
{  
   ServiceHost host = new DerivedHost( typeof( MyService ) );  
   host.Open();  
  
   ...  
}  

现在,你已将自定义逻辑封装到一个干净的抽象中,可以在许多不同的主机可执行文件中轻松重复使用。

目前还不清楚如何从 Internet Information Services(IIS)或 Windows 进程激活服务(WAS)内部使用此自定义 ServiceHost 。 这些环境不同于自托管环境,因为宿主环境是代表应用程序实例化 ServiceHost 的。 IIS 和 WAS 托管基础结构并不了解您的自定义 ServiceHost 派生。

ServiceHostFactory 旨在解决从 IIS 或 WAS 中访问自定义 ServiceHost 的问题。 由于派生自 ServiceHost 的自定义主机是动态配置的,并且可能有多种类型,因此宿主环境永远不会直接实例化它。 相反,WCF 使用工厂模式在托管环境和服务的具体类型之间提供间接层。 除非另有说明,否则它会使用ServiceHostFactory的默认实现,该实现返回ServiceHost的实例。 但是,也可以通过在 @ServiceHost 指令中指定工厂实现的 CLR 类型名称来提供自己的返回派生宿主的工厂。

对于简单的情形,实现您自己的工厂的练习应该是简单明了的。 例如,下面是用于返回派生的 ServiceHostFactory 的自定义 ServiceHost

public class DerivedFactory : ServiceHostFactory  
{  
   public override ServiceHost CreateServiceHost( Type t, Uri[] baseAddresses )  
   {  
      return new DerivedHost( t, baseAddresses )  
   }  
}  

若要使用此工厂而不是默认工厂,请在指令中 @ServiceHost 提供类型名称,如下所示:

<% @ServiceHost Factory="DerivedFactory" Service="MyService" %>

尽管对于从 ServiceHost 返回的 CreateServiceHost 可以执行什么操作没有技术限制,但建议您尽可能使工厂实现简单化。 如果你有大量的自定义逻辑,最好将该逻辑放在主机内部而不是工厂内部,以便可以重复使用。

托管 API 还有一个层,应该在此处提及。 WCF 还具有ServiceHostBaseServiceHostFactoryBase,从中分别派生出ServiceHostServiceHostFactory。 这些是针对更高级的场景存在的,在这些场景中,你必须用自己的定制设计来替换掉大部分的元数据系统。