文章教程

16.4端点

8/31/2020 9:19:23 PM 人评论 次浏览

16.4 端点

每个WCF服务都会关联到一个用于定位服务位置的地址,一个用于定义如何与服务进行通信的绑定,以及一个告知客户端服务能做什么的合约。这三样共同组成了服务的端点。

每个端点都必须完整拥有这三个组成部分,主机通过公开端点来对外提供服务。理论上,端点就是服务的外部交互接口,就像CLR或者COM接口。每个服务至少需要公开一个端点,服务上所有的端点都必须拥有唯一的定位地址,单个服务可以提供多个端点供不同类型的客户端调用。这些端点可以使用相同或不同的绑定对象,可以拥有相同或不同的服务契约。但是对于单个服务的不同端点,它们之间没有任何关联。

下面对如何通过配置文件和编程方式定义端点进行介绍。

16.4.1 通过配置文件方式

这种方式是将端点的信息保存到主机的配置文件中,通常是app.config文件或者web.config文件。

假设使用如下代码定义了一个服务合约及其实现类。

    //指定命名空间
    namespace MyNameSpace
    {
        [ServiceContract]
        public interface IMyContract
        {
          //这里是IMyContract接口的定义
        }
        public class MyService : IMyContract
        {
          //这里是IMyContract接口的实现
        }
    }

如下给出了针对这个WCF服务的端点信息,其中包含服务的完整名称、绑定类型、合约的完整名称等。

    <system.serviceModel>
        <services>
          <service name = "MyNameSpace.MyService">
              <endpoint
                  address  = "http://localhost:8000/MyService/"
                  binding  = "wsHttpBinding"
                  contract = "MyNameSpace.IMyContract"
              />
          </service>
        </services>
    </system.serviceModel>

注意

在这里指定的服务名称和服务合约必须是带命名空间的完整名称,否则将无法正确引用其地址。而且地址的类型与绑定类型必须匹配,否则就会在加载服务时导致异常。

当然,也可以在配置文件中为一个单独的服务提供多个端点设置。这些端点可以使用相同的绑定类型,但是必须保证URL是唯一的。例如,如下是多个端点的示例配置文件。

    <service name = "MyService">
        <endpoint
            address  = "http://localhost:8000/MyService/"
            binding  = "wsHttpBinding"
            contract = "IMyContract"
        />
        <endpoint
            address  = "net.tcp://localhost:8001/MyService/"
            binding  = "netTcpBinding"
            contract = "IMyContract"
        />
        <endpoint
            address  = "net.tcp://localhost:8002/MyService/"
            binding  = "netTcpBinding"
            contract = "IMyOtherContract"
        />
    </service>

还可以提供一个或多个默认的基本地址(Base Address),这样在端点设置中只需提供相对地址。多个基本地址之间不能冲突,不能在同一个端口进行监听。

相对地址通过端点绑定类型与基本地址进行匹配,从而在运行时获得完整地址。如果将某个端点设置中的地址设为空值(省略address),则表示直接使用某个相匹配的基本地址。

例如,如下的配置文件演示了这种方式。

    <service name = "MyService">
        <host>
          <baseAddresses>
              <add baseAddress="http://localhost:8080/" />
              <add baseAddress="net.tcp://localhost:8081/" />
          </baseAddresses>
          </host>
          <endpoint
          address  = "MyService"       <! -- http://localhost:8080/MyService -->
          binding  = "wsHttpBinding"
          contract = "IMyContract"
        />
        <endpoint
          address  = "MyService"       <! -- net.tcp://localhost:8081/MyService -->
          binding  = "netTcpBinding"
          contract = "IMyContract"
        />
        <endpoint
          address  = "net.tcp://localhost:8002/MyService/"
          binding  = "netTcpBinding"
          contract = "IMyOtherContract"
        />
    </service>

此外,还可以进一步对端点中的绑定参数进行设置。每种绑定类型可拥有多个名称不同的参数设置,然后在端点的bindingConfiguration属性中指定关联设置名称。

例如,在下面的配置文件中使用bindingConfiguration属性指定关联名称为“TransactionalTCP”的绑定信息。

    <system.serviceModel>
        <services>
          <service name = "MyService">
              <endpoint
                  address  = "net.tcp://localhost:8000/MyService/"
                  bindingConfiguration = "TransactionalTCP"
                  binding  = "netTcpBinding"
                  contract = "IMyContract" />
          </service>
        </services>
        <bindings>
          <netTcpBinding>
              <binding name = "TransactionalTCP"
                  transactionFlow = "true"   />
          </netTcpBinding>
        </bindings>
    </system.serviceModel>

16.4.2 通过编程方式

编程方式配置端点与使用配置文件的方式是等效的。它的优点是不需要编写额外的配置文件,而是通过编程的方式将端点添加到ServiceHost实例中。如下所示为创建ServiceHost实例时可用的两个构造函数形式。

    public ServiceHost(object singletonInstance, params Uri[] baseAddresses);
    public ServiceHost(Type serviceType, params Uri[] baseAddresses);

ServiceHost提供了一个AddServiceEndpoint()方法来向当前的服务中添加端点。如下所示为该方法的重载形式。

    public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address);
    public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address);
    public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri);
    public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri);

在使用时address参数可以是相对地址,也可以是绝对地址,这与使用配置文件时是一致的。例如,下面的代码演示了如何通过编程方式配置端点。

    ServiceHost host = new ServiceHost(typeof(MyService));

    Binding wsBinding  = new WSHttpBinding( );
    Binding tcpBinding = new NetTcpBinding( );

    host.AddServiceEndpoint(typeof(IMyContract), wsBinding, "http://localhost:8000/MyService");
    host.AddServiceEndpoint(typeof(IMyContract), tcpBinding, "net.tcp://localhost:8001/MyService");
    host.AddServiceEndpoint(typeof(IMyOtherContract), tcpBinding, "net.tcp://localhost:8002/MyService");

    host.Open( );

教程类别