[英]How to get current User in base class of service layer in ASP.Net Core?
有如何使用IHttpContextAccessor
在服務層中獲取用戶主體的答案,但它們始終與讓用戶進入服務本身有關,而不是在其基礎(抽象類)中。
我有以下情況:
在 controller 中注入了一個UserService
,它需要這樣:
private IUserService UserService;
public UserController(IUserService userService)
{
UserService = userService;
}
非常標准,這是用於獲取/發布/修補...用戶的服務層。 問題是,這個UserService
繼承了一個叫做ServiceBase
的東西:
public class UserService : ServiceBase, IUserService
{
private IDatabaseService DatabaseService;
public UserService(IDatabaseService databaseService, ServiceManager serviceManager) : base(serviceManager)
{
DatabaseService = databaseService;
}
.. rest of code omitted ...
和ServiceBase
看起來像這樣:
public abstract class ServiceBase
{
internal static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();
private ServiceManager ServiceManager;
public ServiceBase(ServiceManager serviceManager)
{
ServiceManager = serviceManager;
}
... rest of code omitted...
現在,如果我想使用IHttpContextAccessor
我必須將它注入到每個服務中,以便它可以傳遞給ServiceBase
,就像傳遞給它的ServiceManager
(另一個 singleton 服務,與這個問題無關)一樣。 需要ServiceBase
的原因是用於日志記錄,更重要的是,為每個服務提供一種將它們所做的更改(發布、修補、刪除)發布到微服務的 rest 的方法。
啟動看起來像這樣:
services.AddSingleton<ServiceManager>();
services.AddHostedService(provider => provider.GetService<ServiceManager>());
services.AddHttpContextAccessor();
services.AddScoped<IDatabaseService, DatabaseService>();
services.AddScoped<ILoginService, LoginService>();
services.AddScoped<IUserService, UserService>();
有沒有辦法在這個ServiceBase
中獲取IHttpContextAccessor
而無需傳遞它? 可以對ServiceManager
提出同樣的問題,因為依賴關系也必須從實現傳遞到基礎 class? 我想知道哪個用戶確實調用了 controller 操作(以及服務層),而無需在每個控制器和/或服務中編寫一堆樣板代碼。
另一種詢問方式是是否可以在服務層內部解決 singleton 服務(如IHttpContextAccessor
和ServiceManager
)而不在每個服務中注入它們?
簡短的回答:你不能。
錯誤的答案:你不應該。 但是您可以使用 ServiceLocator 。
替代答案:我們可以使參數傳輸不那么痛苦。
不要將ServiceManager
傳遞給基礎 class,而是將ServiceBaseServiceContext
傳遞給它:
public class ServiceBaseServiceContext
{
public ServiceManager ServiceManager {get;}
public IUserService UserService {get;}
public ServiceBaseServiceContext(ServiceManager serviceManager, IUserService userService)
{
ServiceManager = serviceManager;
UserService = userService;
}
}
這樣,無論您需要多少服務,您都只有一個參數。
public abstract class ServiceBase
{
private ServiceManager _serviceManager;
private IUserService_userService;
public ServiceBase(ServiceBaseServiceContext serviceContext)
{
_serviceManager = serviceContext.ServiceManager;
_userService = serviceContext.UserService;
}
}
ServiceBaseServiceContext
還需要在您的 ServiceCollection 中注冊以使其工作:
// depending on the services maybe Scoped
services.AddTransient<ServiceBaseServiceContext>();
除了創建ServiceBaseServiceContext
之外,您還可以將IServiceProvider
傳遞給ServiceBase
,但這與 ServiceLocator 相同,這很糟糕,因為它隱藏了依賴項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.