注册表:
container.Register<IAuthenticationHandler, AuthenticationHandler>(Lifestyle.Transient);
container.Register<IUserHandler, UserHandler>(Lifestyle.Transient);
1级:
public UserHandler(IAuthenticationHandler authenticationHandler)
{
_authenticationHandler = authenticationHandler;
}
第2类:
public AuthenticationHandler(IUserHandler userHandler)
{
_userHandler = userHandler;
}
我知道什么是循环问题。当初始化userhandler时,它将注入authenticationhandler实现,然后尝试创建userhandler实例并开始循环…
我的问题是如何解决这个问题(简单的注射器)这种情况和其他我需要这样注射的地方?
谢谢您!
更新:
function AddUser(User user){ // User Handler
_authenticationHandler.GenerateRandomSalt();
string hashedPassword = _authenticationHandler.HashPassword(user.Password.HashedPassword, salt);
}
function Authenticate(string username, string password){ // Authentication Handler
_userHandler.GetUserByUsername(username?.Trim());
}
基本上,我需要调用authenticationhandler中的userhandler来获取用户并验证是否存在用户。
我需要调用userhandler中的authenticationhandler来获取对密码进行salt和散列的函数。
我想我可以调用存储库来获取用户,但我不应该检查服务处理程序,以防在用户服务中做了更多的事情
最佳答案
循环依赖性通常是由SOLID原则冲突引起的,因为具有太宽接口和太多功能的类更可能需要彼此的功能。
我相信在您的情况下也是这样,因为UserHandler.AddUser
功能依赖于AuthenticationHandler.GenerateRandomSalt
和HashPassword
功能,而它不同于AuthenticationHandler
(即Authenticate
)功能依赖于UserHandler
的另一个功能。这强烈表明IAuthenticationHandler
抽象实际上违反了Interface Segregation Principle并且其实现违反了Single Responsibility Principle。
解决方案是将IAuthenticationHandler
及其实现分成多个独立的部分。例如
interface IPasswordUtilities {
// NOTE: I believe GenerateRandomSalt is an implementation detail;
// it should not be part of the interface
string HashPassword(string plainPassword);
}
interface IAuthenticationHandler {
void Authenticate(string username, string password);
}
class PasswordUtilities : IPasswordUtilities {
// implementation
}
class AuthenticationHandler : IAuthenticationHandler {
public AuthenticationHandler(IUserHandler userHandler, IPasswordUtilities utilities) {
...
}
}
class UserHandler : IUserHandler {
public UserHandler(IPasswordUtilities utilities) { ... }
public void AddUser(User user) {
string hashedPassword = _utilities.HashPassword(user.Password.HashedPassword);
}
}
这将优雅地解决您的问题,因为您:
通过将逻辑的一部分提取到一个更小、更集中的类中来移除循环依赖关系
通过修复SRP和ISP违规,可以使代码库更易于维护。
结束图如下所示:
new AuthenticationHandler(
new UserHandler(
new PasswordUtilities()),
new PasswordUtilities());