【问题标题】:Inject ApplicationUser in ASP.NET Core MVC在 ASP.NET Core MVC 中注入 ApplicationUser
【发布时间】:2017-09-05 10:54:48
【问题描述】:

我有一个需要ApplicationUser 的类(来自 ASP.NET Identity)。该实例应该是当前用户。

public class SomeClass
{
    public SomeClass(ApplicationUser user)
    {

目前,我正在做的是从控制器注入当前用户:

var currentUser = await _userManager.GetUserAsync(User);
var instance = new SomeClass(currentUser);

现在我想使用微软提供的依赖注入。我不知道如何将ApplicationUser 添加到服务中。它需要User,这是控制器的一个属性。

那么如何通过微软提供的DI注入ApplicationUser(当前用户的实例)呢?

【问题讨论】:

  • 一般来说,你应该注入依赖项,而不是数据。最好在调用每个方法(或显式调用某些Init(context))时提供所需的上下文(在您的情况下是调用用户),以便该类型的消费者更加了解实际需求。由 DI 在幕后自动注入上下文将提高​​您的 DI 技能,但可能会在未来导致不一致。
  • @haim770 谢谢。我想我只是懒惰,不想在每个方法调用中都提供它。您说的Init(context) 可能是另一种选择,我想知道如何强制调用它。
  • 正如@haim770 所说,防止将运行时数据注入到您的组件中。更多详情请阅读this

标签: c# dependency-injection asp.net-core asp.net-core-mvc asp.net-core-identity


【解决方案1】:

您可以将UserManager<ApplicationUser>IHttpContextAccessor 都注入到您的类的构造函数中,然后:

public class SomeClass
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IHttpContextAccessor _context;
    public SomeClass(UserManager<ApplicationUser> userManager,IHttpContextAccessor context)
    {
        _userManager = userManager;
        _context = context;
    }

    public async Task DoSomethingWithUser() {
        var user = await _userManager.GetUserAsync(_context.HttpContext.User);
        // do stuff
    }
}

如果您不想直接依赖 IHttpContextAccessor 但仍想使用 DI,您可以创建接口来访问您的用户:

public interface IApplicationUserAccessor {
    Task<ApplicationUser> GetUser();
}

public class ApplicationUserAccessor : IApplicationUserAccessor {
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IHttpContextAccessor _context;
    public ApplicationUserAccessor(UserManager<ApplicationUser> userManager, IHttpContextAccessor context) {
        _userManager = userManager;
        _context = context;
    }

    public Task<ApplicationUser> GetUser() {
        return _userManager.GetUserAsync(_context.HttpContext.User);
    }
}

然后在DI容器中注册并注入SomeClass

public class SomeClass
{
    private readonly IApplicationUserAccessor _userAccessor;
    public SomeClass(IApplicationUserAccessor userAccessor)
    {
        _userAcccessor = userAccessor;
    }

    public async Task DoSomethingWithUser() {
        var user = await _userAccessor.GetUser();
        // do stuff
    }
}

其他选项包括(如 cmets 中所述)不注入任何东西,但需要将 ApplicationUser 作为参数传递给需要它的方法(好选项),并且在使用任何具有特殊 Initialize(user) 方法的方法之前需要初始化(不太好, 因为你不能确定在使用其他方法之前调用了这个方法)。

【讨论】:

  • 如果SomeClass 在不同的程序集中声明,这将强制它依赖于Microsoft.AspNetCore.Http
  • @haim770 你是对的,最好不要注入 ApplicationUser 而只是接受它作为方法的参数。但是,如果 OP 仍然想通过 DI 获得它 - 这是一个可能的选择。
  • 我的想法完全一样,这是一个替代方案,但不想与 HttpContext 绑定
  • @dpp 你可以避免这种情况,你甚至可以自己注入ApplicationUser - 但我建议不要这样做。做依赖解决期间可能会抛出的繁重事情不是一个好主意。如果你想通过注入路径 - 使用 Task&lt;ApplicationUser&gt; GetUser() 方法创建一些 IApplicationUserAccessor 并将这个注入到你的类中。
  • @dpp 我已经用 IApplicationUserAccessor 的示例更新了答案。
猜你喜欢
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多