【问题标题】:WCF data contract design with dependency injection使用依赖注入的 WCF 数据合约设计
【发布时间】:2011-03-11 16:37:00
【问题描述】:

所以我有一个分层的应用程序,我在上面添加了一个 WCF 服务接口。该服务只是一个外观,我们所有的业务逻辑都已经存在于业务逻辑层 (BLL) 中的业务对象 (BO) 中,业务逻辑层 (BLL) 是一个类库。在 BLL 中,我们使用构造函数注入将依赖项注入 BO。这一切都适用于良好的单元测试等。关于问题......

通常我会简单地为每个服务方法创建一组请求/响应对象作为 DataContracts,并为操作提供适当的属性。如果操作需要将我们的“实体”之一传入或传出该方法,我只需定义该类型的属性,一切都会好起来的(我们所有的 BO 都是可序列化的)。但是,当这些“实体”之一被传递到服务方法时,WCF 会反序列化该对象,而不会调用我们定义的构造函数,因此,依赖关系不会解析。

让我们使用名为 CreateSomething 的服务方法的例子。我通常会将其定义为具有如下签名的服务操作:

CreateSomethingResponse CreateSomething(CreateSomethingRequest request);

CreateSomethingRequest 将是一个 DataContract 并且在其属性中具有 Something 类型的属性,该属性表示正在传递给服务的“实体”。在这种情况下,Something 是一个业务对象,它期望在实例化时从 DI 容器接收 ISomethingRepository 接口的实例 - 正如我上面所说的那样,它不会当 WCF 反序列化服务器上​​的对象时发生。

选项 #2 是从 DataContract 中删除 Something 属性,并在我的 DataContract 中明确定义每个属性,然后在我的服务方法中,创建 Something 的新实例strong> 类,让容器注入依赖项,然后将属性值从 DataContract 对象映射到 BO。我当然可以这样做,但我担心现在有两个地方可以进行更改,例如,如果我想向 Something 类型添加一个属性。并且,有很多属性,有很多代码重复。

有没有人跨过这座桥,如果有,您能否分享一下您的想法以及您在自己的应用程序中遇到或将如何处理这种情况?谢谢!!!

【问题讨论】:

    标签: wcf dependency-injection datacontract


    【解决方案1】:

    你的问题有两个答案:

    首先:不要发送您的实体,而是使用数据传输对象。您的实体是具有逻辑和数据的业务对象。业务对象的逻辑最有可能用于控制数据。因此,让业务对象在业务层控制其数据并仅交换虚拟 crate。

    第二:如果您不想遵循第一种方法,请查看您的 IoC 容器的文档。通常有两种解决依赖关系的方法。例如 Unity 提供:

    • Resolve - 构建新实例并注入所有依赖项(构造函数注入所必需的)
    • BuildUp - 获取现有实例并解析所有属性依赖项。这应该是您的选择。

    【讨论】:

      【解决方案2】:

      感谢 Ladislav 的回答,因为您确认了我的想法。

      我最终做的是稍微改变我的方法。我意识到我对业务对象的使用本身是多余的和不必要的。或者,也许,只是被误导了。在评估我的要求时,我意识到我可以“简化”我的方法并使一切正常。通过查看应用程序中的每个逻辑层并查看需要在层之间传递哪些数据,我发现了一个可行的设计。

      首先,对于我的业务逻辑层,我实现了一个工作单元对象,而不是业务对象:SomethingManagerSomethingManager 与我的根 Something 实体相关联,因此我想对 Something 执行的任何操作都通过 SomethingManager。这包括 GetById、GetAll、Save 和 Delete 等方法。

      SomethingManager 类在其构造函数中接受两个对象:IValidatorISomethingRepository。这些将由 IoC 容器注入。前者让我可以使用我们选择的任何框架(最初是验证应用程序块)执行所有必要的验证,而后者让我对持久性无知,并抽象了今天 Linq-to-SQL 的使用,并使以后升级到 EF4 变得更加容易。

      对于我的服务层,我已将 IoC 容器(在本例中为 Unity)连接到 WCF,因此服务实例由容器创建。这允许我将 ISomethingManager 的实例注入到我的服务中。使用该接口,我可以打破依赖关系并轻松地对服务类进行单元测试。另外,由于容器正在注入 ISomethingManager 实例,因此它正在构建它并自动解析它的依赖关系。

      然后我创建了 DataContracts 来表示数据在通过服务通过网络传输时应该如何显示。每个请求/响应对象都包含这些 DataContracts 作为 DataMembers,而不是直接引用我的实体类(或 BO)。由服务方法来映射来自或去往业务逻辑层的数据(通过 ISomethingManager) - 使用 AutoMapper 使这变得干净和高效。

      回到数据层,我通过定义一个部分类来扩展生成的实体类,该类从 BLL 实现所需的接口。例如,Something L2S 实体有一个实现 ISomething 的部分定义。 ISomethingSomethingManager(以及 ISomethingManager 接口)和 ISomethingRepository 的共同作用,使得查询数据库并将 L2S 实体向上传递,以供服务层使用和传递(服务层无需了解或依赖于 L2S 实现)。

      感谢任何人对此方法提出的任何评论、问题、批评或建议。

      【讨论】:

        猜你喜欢
        • 2011-03-01
        • 2013-08-18
        • 2012-02-09
        • 2011-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多