BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

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

| 作者 Hartmut Wilms 关注 0 他的粉丝 ,译者 陈黎夫 关注 0 他的粉丝 发布于 2008年1月12日. 估计阅读时间: 8 分钟 | ArchSummit北京2018 共同探讨机器学习、信息安全、微服务治理的关键点

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

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT