2011-10-10 58 views
2

我有一个IUserService(和其他服务),我散装我ServiceInstaller.cs登记:看似循环依赖造成的问题与温莎城堡

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

我然后我有IAuthenticationService我注册成为我的通用WindsorInstaller.cs文件:直到我在UserService添加IAuthenticationService公共财产

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

现在事情都工作得很好。

似乎有一个圆形dependacy或当事情获得注册的一些时间问题,因为我得到的错误:

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. 

我怎样才能解决这个问题呢?

+1

循环依赖可以通过使用属性注入来解决。 – Steven

+0

所以,如果它是构造函数注入它不会工作,但与财产,它会?这是为什么? – Blankman

+1

要构建'UserService',你必须调用它的构造函数。要做到这一点,你必须有一个'AuthenticationService',它需要在构造函数中传递一个'UserService',它需要'AuthenticationService',这需要... –

回答

6

您需要:

  1. 摆脱你的循环依赖(这是首选),或在附近
  2. 工作,通过使用属性注入,而不是构造函数注入。

使用属性注入(如Steven's answer所示)可以创建类的实例,而无需在创建时提供所有依赖关系。缺点是对于类的用户来说,他们不需要做实例化和完全配置实例。

对于如何重构删除ciruclar依赖看到MISKO Hevery这篇博客文章一个很好的解释:

1

这里是你的情况我了解:

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

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

你会如何创建这两个类的实例,在每个班级的大多数单实例创建?

4

属性注入将解决您的问题,因为它打破了依赖周期。看看Krzysztof的例子,并尝试实例化一个UserService;你不能。现在就来看看下面的例子:从构造函数参数属性

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

public class AuthenticationService 
{ 
    AuthenticationService() { } 

    public UserService UserService { get; set; } 
} 

在这个例子中,AuthenticationServiceUserService依赖关系“提升”。现在,您可以创建这样一个用户服务:

var a = new AuthenticationService(); 
var s = new UserService(a); 
a.UserService = s; 

打破循环依赖关系可以用财产注入和任何依赖注入框架可以被配置为允许财产注入来完成。

+4

+1这是直接的解决方案。但值得指出的是,循环依赖通常是设计缺陷的一种表现。更好的解决方案是执行根本原因分析以完全消除循环依赖 –

+5

此外,我想指出的是,从API设计的角度来看,构造函数注入和属性注入并不等价,因为它们意味着不同的保证该类的不变量。 –

+0

我完全同意Mark对此的看法。 – Steven