看似循环的依赖导致Castle Windsor的问题

时间:2011-10-10 16:15:52

标签: c# dependency-injection castle-windsor

我有一个IUserService(和其他服务),我在ServiceInstaller.cs中批量注册:

  container.Register(
                AllTypes.FromAssemblyContaining<UserService>()
                .Where(type => type.Name.EndsWith("Service"))
                .WithService.DefaultInterface()
                .Configure(c => c.LifeStyle.Singleton)
                );

然后我有IAuthenticationService,我在我的通用WindsorInstaller.cs文件中注册:

  container.Register(Component.For(typeof (IAuthenticationService))
                .ImplementedBy(typeof(AuthenticationService)));

现在一切正常,直到我在UserService中为IAuthenticationService添加公共属性。

当事情被注册时,似乎存在循环依赖或某些时间问题,因为我收到了错误:

Can't create component 'ABCD.Services.UserService' as it has dependencies to be satisfied.
ABCD.Services.UserService is waiting for the following dependencies:

Services:
- ABCD.Services.Interfaces.IAuthenticationService which was registered but is also waiting for dependencies.

ABCD.Services.AuthenticationService is waiting for the following dependencies:

Services:
- ABCD.Services.Interfaces.IUserService which was registered but is also waiting for dependencies. 

如何解决此问题?

3 个答案:

答案 0 :(得分:7)

您需要:

  1. 摆脱循环依赖关系(这是首选选项)或
  2. 使用属性注入而不是构造函数注入来解决它们。
  3. 使用属性注入(如Steven's answer中所示)允许您创建类的实例,而无需在创建时提供所有依赖项。缺点是,对于类的用户来说,实例化和完全配置实例需要做些什么并不明显。

    有关如何重构以删除ciruclar依赖关系的详细解释,请参阅MiškoHevery撰写的这篇博文:

答案 1 :(得分:4)

属性注入将解决您的问题,因为它打破了依赖循环。只需看看Krzysztof的例子并尝试实例化一个UserService;你不能。现在看一下下面的例子:

public class UserService
{
    UserService(AuthenticationService a) { }
}

public class AuthenticationService 
{
    AuthenticationService() { }

    public UserService UserService { get; set; }
}

在此示例中,UserService的{​​{1}}依赖项从构造函数参数“提升”到属性。现在您可以创建这样的用户服务:

AuthenticationService

可以使用属性注入来完成循环依赖性,并且可以配置任何依赖注入框架以允许属性注入。

答案 2 :(得分:1)

这是我理解的情景:

public class UserService
{
   UserService(AuthenticationService a){}
}

public class AuthenticationService 
{
   AuthenticationService (UserService a){}
}

如何创建两个类的实例,最多创建每个类的单个实例?