具有依赖注入的WCF数据协定设计

时间:2011-03-11 16:37:01

标签: wcf dependency-injection datacontract

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

通常我只是为每个服务方法创建一组Request / Response对象作为DataContracts,并具有适当的操作属性。如果操作需要将一个“实体”传递给方法或从方法传递,我只需定义该类型的属性,一切都会好的(我们所有的BO都是可序列化的)。但是,当其中一个“实体”传递给服务方法时,WCF会反序列化该对象,而不会调用我们已定义的构造函数,因此,依赖项无法解析。

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

CreateSomethingResponse CreateSomething(CreateSomethingRequest request);

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

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

是否有人越过这座桥梁,如果是这样,您能否分享您的想法,以及您在自己的应用中如何处理或接受这种情况? THX !!!

2 个答案:

答案 0 :(得分:2)

您的问题有两个答案:

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

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

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

答案 1 :(得分:0)

谢谢,拉迪斯拉夫,你的回答,因为你确认了我已经知道的事情。

我最终做的是改变我的方法。我意识到我对业务对象的使用本身就是过度和不必要的。或许,只是误导。在评估我的要求时,我意识到我可以“简化”我的方法并使一切工作。通过在我的应用程序中获取每个逻辑层并查看需要在层之间传递的数据,我发现了一个有效的设计。

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

SomethingManager 类在其构造函数中接受两个对象: IValidator&lt; Something&gt; ISomethingRepository 。这些将由IoC容器注入。前者允许我使用我们选择的任何框架(最初是验证应用程序块)执行所有必要的验证,后者使我无法忍受并且今天使用Linq-to-SQL进行抽象,并使以后更容易升级到EF4。

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

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

回到数据层,我只是通过定义一个从BLL实现所需接口的部分类来扩展生成的实体类。例如, Something L2S实体具有实现 ISomething 的部分定义。并且 ISomething SomethingManager (以及 ISomethingManager 界面)和 ISomethingRepository 的工作方式,可以非常轻松地查询数据库并将L2S实体传递到链上,以便服务层使用和传递(没有服务层对L2S实现有任何知识或依赖)。

我感谢任何人对此方法的任何评论,问题,批评或建议。