WCF 扩展之我见: ServiceHostFactory

本系列索引,请见《开篇

该系列前几篇介绍了 WCF 运行时中的不同扩展点,并且在《Behaviors》文中指出可以通过三种方式来应用这些这些扩展点:Attribute、配置文件及编程方式。这里指的编程方式,就是指在 ServiceHost 中编写代码来应用我们自定义的扩展。

ServiceHost 简介

顾名思义,ServiceHost 就是宿主的意思,一个 SerivceHost 与一个具体的 Service 相关联(,如果要启动多个不同的 Service,需要使用多个 ServiceHost)。WCF 无法自动启动,必须要依赖宿主。这些宿主可以是类似控制台、Winform 的自宿主,也可以是 IIS/WAS 这类的宿主。而这里的宿主最终都是通过实例化ServiceHost,并调用 ServiceHost.Open 方法来启动宿主。

在《消息处理流程》中,我提到过 ServiceHost 在启动阶段所做的事情:初始化所有服务描述(Description)、初始化 ServiceHost 运行时环境、启动监听。


下面的例子描述了一段使用了 ServiceHost 的代码摘自 MSDN:

// Host the service within this EXE console application.
public static void Main()
{
  using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
  {
      try
      {   
          // Open the ServiceHost to start listening for messages.
          serviceHost.Open();        
          
          // The service can now be accessed.
          Console.WriteLine("The service is ready.");
          Console.WriteLine("Press <ENTER> to terminate service.");
          Console.ReadLine();      
          
          // Close the ServiceHost.
          serviceHost.Close();
       }    
       catch (TimeoutException timeProblem)
       {
          Console.WriteLine(timeProblem.Message);
          Console.ReadLine();
       }    
       catch (CommunicationException commProblem)
       {
          Console.WriteLine(commProblem.Message);
          Console.ReadLine();
       }
    }
}


ServiceHostFactory 简介

对于自宿主这类应用程序,那 ServiceHost 就够用了。但是如果需要部署在 IIS/WAS 上的话,由于这些宿主环境自已负责构建 ServiceHost 实例,我们无法控制。面对这种情况,WCF 提供了 ServiceHostFactory,让 IIS/WAS 通过它来创建 ServiceHost 实例。

而我们则可以通过继承 ServiceHostFactory 来添加自定义的逻辑。


什么时候需要扩展 ServiceHost ?

有些时候,我们不想使用默认的配置文件(web.config,app.config) 也不想让 Attribute 来污染代码,且还希望逻辑能被重用。

using (ServiceHost host = new ServiceHost(typeof(Service1)))
{
    //Add Descriptions
    host.Description.Behaviors.Add(new MyBehavior());

    //Add endpoint
    host.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "");

    host.Open();

    //...
}

使用上面的代码,当把寄宿环境换成 Winform、WPF,就需要重复写上述逻辑,不利于维护。此时,就应该考虑使用自定义的 ServiceHost 来包装这些逻辑。


扩展 ServiceHost

与之前的扩展不太一样的是,ServiceHost 及 ServiceHostFactory 都是具体的类而非接口,我们只需要继承它们,然后 override 某些方法就可以了。我们可以把逻辑移动到 OnOpening 这个方法。

public class MyServiceHost:ServiceHost
{
    protected override void OnOpening()
    {
        //Add Descriptions
        this.Description.Behaviors.Add(new MyBehavior());

        //Add endpoint
        this.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "");

        base.OnOpening();
    }
}

之所以要放在 OnOpening 中是为了确保这些初始化的动作在 Open 之前完成。因为在 Open 之后,这部分设置就变成只读的了,无法进行修改(,即便修改,也不会有任何变化)。



扩展 ServiceHostFactory

前面说了,当需要部署在 IIS/WAS 中,需要借助 ServiceHostFactory。

由于 ServiceHostFactory 存在于 System.ServiceModel.Activation 名称空间中,所以要先引入程序集 "System.ServiceModel.Activation.dll"。

之后,我们就可以通过复写 ServiceHostFactory 中的 CreateServiceHost 来进行扩展了,如:

public class MyServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new MyServiceHost();
    }
}


想要 IIS/WAS 能够使用它,还必须要添加一个 svc 文件,该文件中的标记如下:

<% @ServiceHost Factory="MyServiceHostFactory" Service="Service1" %>


考虑到重用的场景,一般建议尽可能把逻辑放在自定义的 ServiceHost 中,保持 ServiceHostFactory 越简单越好。

参考链接

WCF Extensibility – ServiceHostFactory

Extending Hosting Using ServiceHostFactory

A Custom ServiceHostFactory

文章索引

[隐 藏]

本站采用知识共享署名 3.0 中国大陆许可协议进行许可。 ©2014 Charley Box | 关于本站 | 浙ICP备13014059号