WCF 终结点解释()

终结点

服务与地址、绑定以及契约有关。其中,地址定义了服 务的位置,绑定定义了服务通信的方式,契约则定义了服务的内容。为便于记忆,我们可以将这种类似于“三权分立”一般管理服务的方式简称为服务的ABC。 WCF用终结点表示这样一种组成关系。终结点就是地址、契约与绑定的混成品(参见图1-5)。

图1-5:终结点

每一个终结点都包含了三个元素,而宿主则负责公开终 结点。从逻辑上讲,终结点相当于服务的接口,就像CLR或者COM接口一样。注意,图1-5使用了传统的“棒棒糖”形式展示了一个终结点的构成。

注意:从概念上讲,不管是C#还是VB,一个接口就 相当于一个终结点:地址就是类型虚拟表的内存地址,绑定则是CLR的JIT(Just-In-Time)编译,而契约则代表接口本身。由于经典的.NET 编程模式不需要处理地址或绑定,你可能认为它们是理所当然存在的。而WCF并未规定地址与绑定,因而必须对它们进行配置。

每个服务至少必须公开一个业务终结点,每个终结点有 且只能拥有一个契约。服务上的所有终结点都包含了唯一的地址,而一个单独的服务则可以公开多个终结点。这些终结点可以使用相同或不同的绑定,公开相同或不 同的契约。每个服务提供的不同终结点之间绝对没有任何关联。

重要的一点是,服务代码并没有包含它的终结点,它们 通常放在服务代码之外。我们可以通过管理方式(Administratively)使用配置文件或者通过编程方式(Programmatically)配 置终结点。

管理方式配置终结点

以管理方式配置一个终结点需要将终结点放到托管进程 的配置文件中,如下的服务定义:

namespace MyNamespace

{

   [ServiceContract]

   interface IMyContract

   {...}

   class MyService : IMyContract

   {...}

}

例1-6演示了配置文件要求的配置入口。在每个服务 类型下列出它的终结点。

例1-6:管理方式配置终结点

<system.serviceModel>

   <services>

      <service name = "MyNamespace.MyService">

         <endpoint

            address  = http://localhost:8000/MyService/

            binding  = "wsHttpBinding"

            contract = "MyNamespace.IMyContract"

         />

      </service>

   </services>

</system.serviceModel>

当我们指定服务和契约类型时,必须使用类型全名。在 本书的其余例子中,为简略起见,我省略了类型的命名空间,但在实际应用中,命名空间是必备的。注意,如果终结点已经提供了基地址,则地址的样式必须与绑定 一致,例如HTTP对应WSHttpBinding。如果两者不匹配,就会在装载服务时导致异常。

例1-7的配置文件为一个单独的服务公开了多个终结 点。多个终结点可以配置相同的基地址,前提是URI互不不同。

例1-7:相同服务的多个终结点

<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>

大多数情况下,我们的首选是管理的配置方式,因为它 非常灵活,即使修改了服务的地址、绑定和契约,也不需要重新编译服务和重新部署服务。

使用基地址

例1-7中的每个终结点都提供了自己独有的基地址。 如果我们提供了显式的基地址,它会重写宿主提供的所有基地址。

我们也可以让多个终结点使用相同的基地址,只要终结 点地址中的URI不同:

<service name = "MyService">

   <endpoint

      address  = "net.tcp://localhost:8001/MyService/"

      binding  = "netTcpBinding"

      contract = "IMyContract"

   />

   <endpoint

      address  = "net.tcp://localhost:8001/MyOtherService/"

      binding  = "netTcpBinding"

      contract = "IMyContract"

   />

</service>

反之,如果宿主提供了与传输样式匹配的基地址,则可 以省略地址项。此时,终结点地址与该基地址完全相同:

<endpoint

   binding  = "wsHttpBinding"

   contract = "IMyContract"

/>

如果宿主没有提供匹配的基地址,则在装载服务宿主时 会抛出异常。

配置终结点地址时,可以为基地址添加相对URI:

<endpoint

   address  = "SubAddress"

   binding  = "wsHttpBinding"

   contract = "IMyContract"

/>

此时,终结点地址等于它所匹配的基地址加上URI。 当然,前提是宿主必须提供匹配的基地址。

绑定配置

使用配置文件可以为终结点使用的绑定进行定制。为 此,需要在<endpoint>节中添加bindingConfiguration标志,它的值应该与<bindings>配置 节中定制的绑定名一致。例1-8介绍了使用这种技术启用事务传播的方法。其中的transactionFlow标志会在第7章详细介绍。

例1-8:服务端绑定的配置

<system.serviceModel>

   <services>

      <service name = "MyService">

         <endpoint

            address  = "net.tcp://localhost:8000/MyService/"

            bindingConfiguration = "TransactionalTCP"

            binding  = "netTcpBinding"

            contract = "IMyContract"

         />

         <endpoint

            address  = "net.tcp://localhost:8001/MyService/"

            bindingConfiguration = "TransactionalTCP"

            binding  = "netTcpBinding"

            contract = "IMyOtherContract"

         />     

      </service>

   </services>

   <bindings>

      <netTcpBinding>

         <binding name = "TransactionalTCP"

            transactionFlow = "true"

         />

      </netTcpBinding>

   </bindings>

</system.serviceModel>

如例1-8所示,我们可以在多个终结点中通过指向定制绑定的方式,重用已命名的绑定配置。

编程方式配置终结点

编程方式配置终结点与管理方式配置终结点等效。但它 不需要配置文件,而是通过编程调用将终结点添加到ServiceHost实例中。这些调用不属于服务代码的范围。ServiceHost定义了重载版本的 AddServiceEndpoint()方法:

public class ServiceHost : ServiceHostBase

{

   public ServiceEndpoint AddServiceEndpoint(Type implementedContract,

                                             Binding binding,

                                             string address);

   //其他成员

}

传入AddServiceEndpoint()方法 的地址可以是相对地址,也可以是绝对地址,这与使用配置文件的方式相似。例1-9演示了编程配置的方法,它配置的终结点与例1-7的终结点相同。

例1-9:服务端编程配置终结点

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();

以编程方式添加终结点时,address参数为 string类型,contract参数为Type类型,而binding参数的类型则是Binding抽象类的其中一个子类,例如:

public class NetTcpBinding : Binding,...

{...}

由于宿主提供了基地址,因此若要使用基地址,可以将 空字符串赋给address参数,或者只设置URI值,此时使用的地址就应该是基地址加上URI:

Uri tcpBaseAddress = new Uri("net.tcp://localhost:8000/");

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

Binding tcpBinding = new NetTcpBinding();

//使用基地址作为地址

host.AddServiceEndpoint(typeof(IMyContract),tcpBinding,"");

//添加相对地址

host.AddServiceEndpoint(typeof(IMyContract),tcpBinding,"MyService");

//忽略基地址

host.AddServiceEndpoint(typeof(IMyContract),tcpBinding,

                               "net.tcp://localhost:8001/MyService");

host.Open();

使用配置文件进行管理方式的配置,宿主必须提供一个 匹配的基地址,否则会引发异常。事实上,编程方式配置与管理方式配置并没有任何区别。使用配置文件时,WCF会解析文件,然后执行对应的编程调用。

绑定配置

我们可以通过编程方式设置绑定的属性。例如,以下代 码就实现了与例1-8相似的功能,启用事务传播:

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

NetTcpBinding tcpBinding = new NetTcpBinding();

tcpBinding.TransactionFlow = true;

host.AddServiceEndpoint(typeof(IMyContract),tcpBinding,

                        "net.tcp://localhost:8000/MyService");

host.Open();

注意,在处理特定的绑定属性时,通常应该与具体的绑 定子类如NetTcpBinding交互,而不是使用抽象类Binding,正如例1-9所示。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值