【发布时间】:2021-08-15 21:14:26
【问题描述】:
我是 C# 和依赖注入的新手。目前我正在开展一个新项目,并希望在技术方面向前迈出一步。
在这个项目中,我遇到了三种导致循环依赖的情况。
我已经阅读了很多这方面的内容,并找到了像 Lazy<T> 和 IServiceProvider 这样的解决方案,但我想学习一个干净的解决方案来解决这个问题,并希望遵循最常见的建议来重构代码。
在这个例子中我们有四个服务:
AccountService -> 登录、注销等
HttpService -> 做 API-Stuff
LogService -> 做一些日志记录
LogRepository -> 用于 EF 的日志记录表/包装器的 CRUD
AccountService 使用HttpService 通过 API 进行身份验证。稍后,我想使用HttpService 通过 API 获取更多数据。 HttpService 现在需要AccountService 来获取用于验证请求的令牌。这会导致循环依赖错误。
账户服务
public interface IAccountService
{
Identity Identity { get; }
Task Login(Credentials Credentials);
Task Logout();
}
public class AccountService : IAccountService
{
public Identity Identity { get; private set; }
private readonly IHttpService _httpService;
private readonly ILogService _logService;
public AccountService(
IHttpService HttpService, ILogService LogService)
{
_httpService = HttpService;
_logService = LogService;
}
public async Task Login(Credentials Credentials)
{
Identity = await _httpService.Post<Identity>(
"api/rest/v1/user/authenticate", Credentials);
}
}
HttpService
public interface IHttpService
{
Task<T> Get<T>(string uri);
Task Post(string uri, object value);
Task<T> Post<T>(string uri, object value);
}
public class HttpService : IHttpService
{
private readonly HttpClient _httpClient;
private readonly IAccountService _accountService;
private readonly ILogService _logService;
public HttpService(
HttpClient HttpClient,
IAccountService AccountService,
ILogService ILogService)
{
_httpClient = HttpClient;
_accountService = AccountService;
_logService = LogService;
}
private async Task AddAuthentication(HttpRequestMessage Request)
{
Request.Headers.Authorization = new AuthenticationHeaderValue(
"bearer", _accountService.Identity.SystemToken);
}
}
解决或正确重新设计此问题的最佳做法是什么?
我有更多的循环依赖,例如在LogRepository 中使用LogService 或在HttpService 中使用LogService(因为HttpService 将日志条目发送到服务器)。
非常感谢您的帮助!
【问题讨论】:
-
您能否以如下方式更新您的代码示例:1. 删除与问题无关的所有依赖项,以及 2. 精简与循环依赖项相关的方法版本,即显示调用
HttpService的AccountService的方法,并显示调用IAccountService的HttpService的方法。 -
也就是说,在不知道细节的情况下,我敢打赌你的
AccountService或HttpService做得太多,换句话说,违反了Single Responsibility Principle。将此类拆分为多个较小的类通常会解决 SRP 违规和循环依赖问题。我在我的书的section 6.3 中详细讨论了这一点。 -
我已经编辑了代码。您现在可以看到呼叫。服务做的不多。 HttpService 仅处理 api 调用,AccountService 仅登录、注销并保存有关当前用户的信息。
-
在不了解您的系统的情况下,
HttpService似乎没有那么有价值,并且可能被过度设计。我建议完全删除这个类,并在您需要进行 HTTP 调用的每个服务中创建HttpClient。
标签: c# .net rest dependency-injection webassembly