【问题标题】:Avoid circular references with services and DI避免使用服务和 DI 进行循环引用
【发布时间】:2011-04-15 04:12:13
【问题描述】:

我有一个包含多个服务类的服务程序集。每个类分组一组相关的服务方法。这些服务使用 IoC 和构造函数注入器进行实例化。

如果我有两个服务类有时可能需要调用另一个中的方法,为了避免循环引用,最好的处理方法是什么?

例如,假设来自两个不同服务类的两个服务方法(不一定是最实际的例子,但为了简单起见):

public class UserService
{
    public void RegisterUser(User user)
    {
        // Do a bunch of stuff needed to register a user

        // Now call out to permission service to set up basic permissions
        _permissionService.SetUpBasicPermissions(user);
    }
}

public class PermissionService
{
    public void GrantPermission(User user, int PermissionId)
    {
        // Add user permission to database

        // Now call out to user service to do some other stuff on the user
        _userService.TakeActionsOnUserAccount(user);
    }
}

以下是我可以看到的选项:

  1. 考虑到需要在两者之间共享功能,这是服务类应合并为一个类的标志。但是,如果是这样的话,我最终会不会得到一个巨大的服务类?是什么决定了它们应该如何拆分?

  2. 不要组合这两个类,而是将共享逻辑的方法移到它们自己的服务类中(将用户和权限特定的逻辑留在它们各自的类中)。如果是这种情况,我最终可能会得到其中几个共享服务,我认为这不是一件好事。

  3. 从一项服务到另一项服务所需的任何操作都应移至调用代码。这对我来说似乎有问题,因为我将删除潜在的依赖逻辑,并使其成为另一层的关注点。换句话说,无论我在哪里调用 _userService.RegisterUser(),我现在都必须在每次调用后立即调用 _permissionService.SetUpBasicPermissions()。

  4. 允许一个服务调用另一个服务,但不能同时调用两者。如果是这种情况,我该选择哪一个?对于无法调用另一个的逻辑,我该怎么办?

  5. 使用委托将依赖的服务方法注入到被调用的服务方法中。 Bleh,这听起来很难看。

这些是我能想到的,但我敢肯定有些我忽略了。

想法?

提前致谢。

【问题讨论】:

标签: design-patterns dependency-injection domain-driven-design inversion-of-control


【解决方案1】:
  1. SRP 原则states that every object should have a single responsibility 所以不能合并类。
  2. 这是发明的继承方式,对公共代码使用抽象类并在之后专门化(不要使用引用)
  3. 依赖逻辑不好,RegisterUser 应该只做那个 Register,而不是给 Permissions。把依赖移到调用层就可以了。
  4. 只有在必要时才这样做,在完成抽象类之后应该有点清楚。不过可以尝试对象组合。
  5. 这叫容器,看完你应该会更好理解:http://www.potstuck.com/2009/01/08/php-dependency-injection

关于循环引用,OOP 原则只是说要避免抽象类和具体类之间的循环引用(好莱坞原则),事实并非如此。可以像你一样使用它们。

但是,您使用的依赖注入非常好,因此您可以提取 SetUpBasicPermissions 并将其放在类之外。

objUser = new User();
objUserService.RegisterUser(objUser);
objPermissionService.SetUpBasicPermissions(objUser);

【讨论】:

    【解决方案2】:

    如果您想让两个服务相互引用,您需要使用属性注入(或方法)而不是构造函数,以便在传递到另一个类之前可以完全创建它们。

    就在某些情况下让一个服务调用另一个服务的设计而言,只要操作的逻辑流程有意义,这是可以的。尽管尽可能将其保持在最低限度是一种更好的设计,因为增加依赖关系会增加耦合并且必须在单元测试中更紧密地映射行为。

    【讨论】:

    • 我最终意识到我最大的依赖是我需要能够检查我的大多数服务的权限,所以我只是打破了这个。我将尝试避免使用循环引用。到目前为止,我已经能够在不影响我的设计的情况下做到这一点。
    猜你喜欢
    • 1970-01-01
    • 2015-09-05
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    相关资源
    最近更新 更多