65.9K
CodeProject 正在变化。 阅读更多。
Home

WCF:正确的方式。快速参考指南

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (17投票s)

2010 年 10 月 1 日

CPOL

6分钟阅读

viewsIcon

72403

downloadIcon

1886

Miguel Castro 开发的手动创建和使用 WCF 服务的开发人员工作流程

引言

Miguel Castro(以下简称 MC)提出了一个有说服力的论点,认为 WCF 服务应用程序的包含项目模板“产生了过多的负担”,并且不利于“最佳实践”。他进一步认为,添加服务引用也“差强人意”。为了更好地说明,他指出 WCF“可能是微软推出的最酷的技术之一”。

WCF 模板方法没有分离契约,将服务紧密耦合到 Web 服务(尽管可以使用其他传输方式),Web 服务 webconfig 包含过多元数据,并且服务引用会重复契约。

MC 的批评总结可以在这里找到。使这篇文章成为一个建设性练习的是,他还概述了一种手动创建和使用 WCF 服务的方法:这种方法是松耦合的,遵循良好的设计标准,最重要的是,易于维护。本文将他的过程分解为一个简洁的开发人员工作流,分为不同的操作和步骤——一个快速参考指南。

vs_new_project_dialog.png

图 1:MC 建议不要使用模板“WCF 服务应用程序”

vs_add_service_reference_dialog.png

图 2:MC 建议不要使用“添加服务引用”功能来引用 WCF 服务。

约定

  • 在项目中,配置文件(Web.configApp.config)中任何非默认的条目都会被添加到名为 Configuration 的文件夹中,并且会在配置文件中添加 configSource 链接。
  • WPF 客户端仅用于演示目的。任何可以进行 WCF 服务调用的客户端都可以使用。
  • 演示代码中提供了 Web 服务和 TCP 主机。也可以使用其他传输方式。文章中分解了 Web 服务。
  • 以下步骤假设已创建新解决方案,并且 .NET Framework 3+ 可用于开发。

设置项目

解决方案被分成以下项目(展示了分离的功能和好处)

  • 模型
    • 功能 - 业务对象定义
    • 好处 - 典型分离;在不同程序集之间重用
  • 契约
    • 功能 - 服务和数据契约
    • 好处 - 在服务和服务的消费者之间重用(面向 SOA 原则)
  • Service
    • 功能 - 一个或多个;包含基于契约的服务方法
    • 好处 - 在其他解决方案中重用;对象模型的过程式入口点
  • 服务主机
    • 功能 - 由代理引用;提供到服务的传输
    • 好处 - 允许多种传输方式(通过其他服务主机)使用服务
  • 客户端代理
    • 功能 - 消费者访问服务实现的入口点
    • 好处 - 在多个客户端之间重用;可以在不同服务主机上使用不同的终结点名称进行重用
  • 客户端
    • 功能 - 服务客户端或消费者
    • 好处 - 典型分离;可以使用各种传输方式访问服务

vs_solution_explorer_1.png

vs_solution_explorer_2.png

图 3:与服务相关的项目
图 4:与传输相关的项目

vs_solution_explorer_3.png

图 5:用户界面项目

此任务可分为四类

  1. 设置服务层
    • 添加“模型”项目
      • 创建新项目 > 类库 > 名称以“Model”结尾
      • 添加对 System.Runtime.Serialization 的引用
      • 为打算使用的每个业务对象添加一个类
      • 在每个类中添加 using 子句以引用 System.Runtime.Serialization
      • DataContractAttribute 添加到类
      • DataMemberAttribute 添加到类的 public 成员
    • 添加“Contract”项目
      • 添加新项目 > 类库 > 名称以“Contract”结尾
      • 为打算使用的每个服务类添加接口
      • 在每个接口中,添加对 System.ServiceModel 的引用
      • ServiceContractAttribute 添加到接口。
      • OperationContractAttribute 添加到接口的成员。
    • 添加“Service”项目
      • 添加新项目 > 类库 > 名称以“Service”结尾
      • 添加对 Model 和 Contract 项目的引用
      • 为您已添加到“Contract”项目中的每个接口添加一个类
      • 在每个类中,添加 using 子句以引用 Model 和 Contract 项目
      • 实现每个接口
  2. 设置传输
    • 对于 Web 服务
      • 添加“Service Host”项目
      • 添加新项目 > ASP.NET Web 应用程序 > 名称以“WebService”结尾
      • 添加对 Service 项目的引用
      • 删除 Default.aspx
      • 为每个服务类添加一个文本文件,并将文件名扩展名更改为 SVC
      • 将以下代码模板(插入服务类的命名空间)添加到文件中
      <%@ ServiceHost
          Service ="namespace.of.service"
      %>
    • 添加“Client Proxy”项目
      • 添加新项目 > 类库 > 名称以“ClientProxy ”结尾
      • 添加对 System.ServiceModel 的引用
      • 添加对 Contract 项目的引用
      • Contracts 中的每个接口添加一个类
      • 在每个类中
        • 添加 using 子句以引用 System.ServiceModel
        • 实现接口
        • 继承 ClientBase<TheInterface>
        • 在每个方法中,通过基类的 Channel 属性引用服务方法
  3. 设置使用者
    • 对于 WPF 客户端
      • 添加新项目 > WPF 应用程序 > 名称以“WpfUi”结尾
      • 添加对 System.ServiceModel 的引用
      • 添加对 ClientProxy, Model Contract 项目的引用
      • App.config configuration/system.serviceModel/client 元素中为服务类添加终结点
      • 在进行服务调用的类中
        • 添加 using 子句以引用 System.ServiceModel, ClientProxy, Model Contract 项目
      • 调用服务
      • 创建新的代理对象
      • 调用代理的方法,该方法映射到服务方法调用
  4. 配置解决方案
    • 设置启动项目
      • 调试本地 TcpHost 项目
        • 在解决方案资源管理器中右键单击解决方案 > 属性
        • 选择启动项目 > 多个启动项目
        • 选择 TcpHost WpfUi 项目

常见维护任务

  1. 添加服务
    • 为服务创建 Interface
    • Service 项目中的新类中实现 interface
    • ClientProxy 中创建一个类,该类实现 ClientBase 和引用该服务的新 interface
    • WebService 中创建一个 SVC 文件(从文本文件重命名),该文件映射到服务命名空间
    • 在 UI 项目中创建一个 endpoint ,该 endpoint 指向 SVC 文件,并指定契约(接口)
    • WebService 中创建一个指向 Service 类的 endpoint
    • 使用 ClientProxy 类使用服务
  2. 添加服务方法
    • 为方法创建 interface 定义
    • Service 项目中的 Service 类中实现该方法
    • ClientProxy 类添加一个方法
    • 使用 ClientProxy 类使用服务方法

关注点

ClientProxy 构造函数有一个参数 endpointConfigurationName ,该参数传递给 ClientBase 构造函数。这仅用于使服务调用能够从使用者路由到任一传输(TCP/HTTP)。在实际应用程序中,这种情况不太可能发生,可以将其删除。将为契约定义单个终结点。

结论

使用 WCF 这一酷炫技术并不意味着你必须放弃良好的设计原则。Miguel Castro 已经将其分解。本文总结了用于实现他的方法的开发人员工作流。

历史

  • 2010-10-04 - 在“添加服务”中添加 WebService 终结点
  • 2010-10-01 - 初始提交
© . All rights reserved.