簡體   English   中英

如何在 ASP.Net Core 服務層的基礎 class 中獲取當前用戶?

[英]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 服務(如IHttpContextAccessorServiceManager )而不在每個服務中注入它們?

簡短的回答:你不能。

錯誤的答案:你不應該。 但是您可以使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM