避免使用服务和DI的循环引用

时间:2011-04-15 04:12:13

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

我有一个包含多个服务类的服务程序集。每个类对一组相关的服务方法进行分组。这些服务使用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. 允许一个服务调用另一个服务,但不能同时调用两个服务。如果是这种情况,我选择哪一个?我怎么办w /那个不能打电话给另一个人的逻辑呢?

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

  6. 这些是我能想到的,但我确信有一些我会忽视。

    思想?

    提前致谢。

2 个答案:

答案 0 :(得分:2)

  1. SRP原则states that every object should have a single responsibility因此合并类不合适。
  2. 这是继承方式发明的方式,使用公共代码的抽象类,并在(不使用引用)后专门化
  3. 依赖逻辑很糟糕,RegisterUser应该只执行Register,而不是授予权限。可以将依赖项移动到调用层。
  4. 只有在你必须这样做时才这样做,你做完abstrat课后应该有点清楚。尝试对象组合。
  5. 它被称为容器,您应该在阅读后更好地理解它:http://www.potstuck.com/2009/01/08/php-dependency-injection
  6. 关于循环引用,OOP原则仅表示避免抽象和具体类之间的循环引用(好莱坞原则),但事实并非如此。可以像你一样使用它们。

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

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

答案 1 :(得分:1)

如果你想让两个服务互相引用,你需要使用Property Injection(或方法)而不是构造函数,这样它们才能在传递到另一个类之前完全创建。

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