首页 文章

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

提问于
浏览
1

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

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

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

CreateSomethingResponse CreateSomething(CreateSomethingRequest request);

CreateSomethingRequest 将是一个DataContract,并且在其属性中具有 Something 类型的属性,表示传递给服务的"entity" . 在这种情况下, Something 是一个业务对象,它希望在实例化时从DI容器接收 ISomethingRepository 接口的实例 - 如上所述,当WCF反序列化服务器上的对象时,这不会发生 .

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

有没有人越过这座桥,如果是的话,你能分享一下你的想法,以及你在自己的应用中如何处理或接受这种情况?谢谢!!!

2 回答

  • 0

    您的问题有两个答案:

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

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

    • Resolve - 构建新实例并注入所有依赖项(构造函数注入所必需的)

    • BuildUp - 获取现有实例并解析所有属性依赖项 . 这应该是你的选择 .

  • 2

    谢谢你,拉迪斯拉夫,你的回答,因为你确认了我脑子里已有的东西 .

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

    首先,对于我的业务逻辑层而不是业务对象,我实现了一个工作单元对象: SomethingManager . SomethingManager 绑定到我的根 Something 实体,因此我想要在 Something 上执行的任何操作都是通过 SomethingManager 完成的 . 这包括GetById,GetAll,Save和Delete等方法 .

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

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

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

    回到数据层,我只是通过定义一个从BLL实现所需接口的部分类来扩展生成的实体类 . 例如, Something L2S实体具有实现 ISomething 的部分定义 . 并且 ISomethingSomethingManager (和 ISomethingManager 接口)和 ISomethingRepository 的工作方式,使查询数据库变得非常容易,并将L2S实体传递到链上,以便服务层使用和传递(没有服务层具有任何知识或依赖性)关于L2S实施) .

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

相关问题