InfoQ

新闻

在WCF服务的实现中进行依赖注入

作者 Hartmut Wilms 译者 陈黎夫 发布于 2008年1月11日 上午5时24分

社区
.NET
主题
.NET框架,
Web服务
标签
依赖注入,
WCF

实现WCF服务的一个常见的做法就是将程序分为服务、业务逻辑以及数据访问层。而这些层次之间的关系则恰好可以通过依赖注入容器在程序运行时进行关联。

Don Smith服务架构概念模型(Service Architecture Concept Model)一文中提出了WCF服务门面的设计方法。依照这样的设计,服务将发布一个由业务逻辑层组件构成的接口/契约。而这些业务逻辑层组件则又依赖于资源访问层中的数据访问组件。

一般来讲,层与层之间的依赖关系均被硬编码在服务以及组件的实现代码中,这也让单元测试显得举步维艰。为了改善这种情况,Pablo M. Cibraro通过实现一个WCF依赖注入行为,在运行时将组件之间的关系进行注入。在他的方法中,作为依赖注入容器的是ObjectBuilder,而在Oran DennisonWCF服务的依赖注入中,却异曲同工地选择了Spring.NET

如下代码演示了Oran的实现方式中建立依赖关系的方法:

[ServiceContract]
public interface IServiceContract {
[OperationContract]
...
}

public class ServiceLayer : IServiceContract {
IBusinessLogic _businessLogic;

public ServiceLayer(IBusinessLogic businessLogic) {
_businessLogic = businessLogic;
}
...
}

public interface IBusinessLogic {
...
}

public class BusinessLogic : IBusinessLogic {
IDataAccess _dataAccess;

public BusinessLogic(IDataAccess dataAccess) {
_dataAccess = dataAccess;
}
...
}

public interface IDataAccess {
...
}

public class DataAccess : IDataAccess {
...
}

可以看到,服务层的实现则依赖于业务逻辑组件,而业务逻辑的实现则相应地依赖于数据访问组件。这样,建立依赖关系的代码将如下所示:

return new ServiceLayer(new BusinessLogic(new DataAccess()));

一般来讲,依赖注入容器是通过在配置中提供实现类到接口的映射关系来实现注入的。而这些配置则能够很容易地在运行时根据需要进行调整或改变。例如,有时为了方便单元测试,我们可能需要改用Mock对象。对于这种情况,Pablo给出了解决方案:

这简直是小菜一碟——(对于依赖注入容器)我们所要做的只是调整一下映射规则,否则容器无法知晓应该创建哪种对象的实例。现在就让我们通过一种可扩展的方法尝试配置该WCF服务。我们都知道,WCF支持一个名为IInstanceProvider的扩展,用来控制WCF实例的生命周期。我们正是要通过它来加载新的代码,并在运行时将层与层之间的依赖关系注入。
public class DIInstanceProvider : IInstanceProvider {   
[...]


public object GetInstance(InstanceContext instanceContext, Message message) {
DependencyContainer container = new DependencyContainer();
foreach (TypeMapping typeMapping in this.typeMappings) {
container.RegisterTypeMapping(typeMapping.TypeRequested, typeMapping.TypeToBuild);
}
return
container.Get(this.serviceType);
}
[...]
}

随后,该DIInstanceProvider将通过一个IServiceBehavior在运行时接入到分配程序中。类型的映射是通过一个新的WCF配置节实现的,该配置节可以通过BehaviorExtensionElement从配置文件中读取,并传递给DIServiceBehavior实例。在Pablo给出的示例中,配置文件如下所示:

<behaviors>

      <serviceBehaviors>

        <behavior name="Behaviors1">

          <dependencyInjection>

            <typeMappings>

              <add name="DataAccess" typeRequested="SampleService.ICustomerDataAccess, SampleService"

                    typeToBuild="SampleService.CustomerDataAccess, SampleService"/>

              <add name="BusinessComponent" typeRequested="SampleService.ICustomerBusinessComponent, SampleService"

                    typeToBuild="SampleService.CustomerBusinessComponent, SampleService"/>

            typeMappings>

          dependencyInjection>

        behavior>

      serviceBehaviors>   

behaviors>

Pablo给出了他的示例代码。我们也能够容易地将该代码转化为Oran等使用其他依赖注入容器(例如Castle Windsor)的实现方法。

查看英文原文:Injecting Implementation Dependencies into WCF Services

深度内容

模块化Java:声明式模块化

本文是模块化Java系列文章的第4篇,介绍的是声明式模块化。文中描述了组件如何以声明的方式来定义并组织在一起,而无需让代码依赖于OSGI API。

Ian Robinson和Jim Webber谈论基于Web的整合

本采访是在伦敦举行的QCon2009上记录的,Ian Robinson和Jim Webber探讨了如何将Web作为整合平台以及REST在理论上和实践中的好处。

项目管理修炼之道(精选版)

项目管理对于项目成败至关重要,但实践中每个项目都有自己的独特性,没有现成的解决方案可以套用。书中从应对实际风险的角度出发,讲述了从项目启动、项目规划到项目结束的整个管理流程,展示了作者的思考过程。本迷你书从原书中精选出5个章节。

那是鸟,还是飞机?不,那是超人!

在这个演讲中,Fred将会揭示敏捷的一些外在因素,并会重点关注敏捷获得成功的内在原因。从案例研究和真实的项目经验来看,Fred认为:工具、管理体系都不能让你变得敏捷。敏捷的成功,植根于士气高涨、充分授权的工作者身上,他们能够以不同以往的方式思考问题。

访谈和书摘:Eben Hewitt的新书《Java SOA Cookbook》

Java SOA Cookbook

Eben Hewitt的新书《Java SOA Cookbook》从Java实现的角度讨论了面向服务架构。Eben在书中讨论了SOA基础、工具、最佳实践和SOA治理等主题。

Mark Richard的《Java消息服务》第二版

Mark Richards的新书《Java消息服务》第二版覆盖了JMS的许多主题, 包括发布和订阅模式以及点对点模式,消息过滤和事务等。InfoQ与Mark谈论了跟他的新作。

模块化Java:动态模块化

本文是“模块化Java”系列文章的第三篇,讨论动态模块化,内容涉及如何解析bundle类、bundle如何变化、以及bundle之间如何通信。

让测试也敏捷起来

对于测试组织来说,敏捷方法带来的快速迭代却让测试本身变得困难起来:缺乏“足够详细的文档”,缺乏“仔细设计用例的时间”等等。在本演讲中,段念将与大家探讨如何在敏捷过程中进行测试。