16.4端点
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( );
上一篇:16.3WCF核心元素
下一篇:17.1了解配置文件
